创建一个 for 循环来整合 powershell 菜单驱动的脚本 [英] Creating a for loop to consolidate powershell menu-driven script

查看:35
本文介绍了创建一个 for 循环来整合 powershell 菜单驱动的脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在编写脚本来安装需要多个安装程序才能正常工作的产品.有些需要安装某些功能,而有些则是可选的.我的脚本是菜单驱动的,它启用了可选的安装程序并且运行良好.

I've been working on a script to install a product that requires several installers to work correctly. Some require certain features to be installed, while others are optional. My script is menu-driven, which enables the optional installers and works reasonably well.

大部分代码都被重用了,我想把它合并成一个单一的 for 循环,但我的 PShell-foo 还不是黑带级别.我熟悉多变量 for 循环的 CSV 输入,但认为这可以通过代码中生成的数组来完成.你们中的一位大师可以训练这个新手吗?

Much of the code is re-used and I'd like to consolidate it into a single for-loop, but my PShell-foo is not yet black-belt level. I am familiar with CSV input for multi-variable for-loops, but think this can be done with an array generated in the code. Can one of you masters train this neophyte?

这是当前代码的净化版本:

Here is a sanitized version of the current code:

# Main Level Menu Choices
switch (Read-Host $Main_Prompt)
    {
        1 {$choice = 1}
        2 {$choice = 2}
        3 {$choice = 3}
        4 {$choice = 4}
        5 {$choice = 5}
        "q" {$choice = q}
    }

if (($choice -eq "q"){
    Write-host "Exiting!"
    exit
}

# Install 1
if (($choice -eq 1) -or ($choice -eq 5)){
    Write-Host "Installing 1"
    $1Path = "$InstallSource\Folder1\file.msi"
    if (Test-Path $1Path) {
        $processInfo = New-Object System.Diagnostics.ProcessStartInfo "msiexec.exe"
        $processInfo.arguments = "/i `"$1Path`" /qr ARGUMENTS"
        $processMSI = New-Object System.Diagnostics.Process
        $processMSI.StartInfo = $processInfo
        $processMSI.Start() | Out-Null
        $processMSI.WaitforExit()

        if ($processMSI.ExitCode -ne 0) {
            Write-Host "The Installer generated error code:" $processMSI.ExitCode "Exiting!"
            exit
        }
    }
    Else {
        Write-host "Installer does not exist. Exiting!"
        exit
    }
}

# Install 2
if (($choice -eq 2) -or ($choice -eq 5)){
    Write-Host "Installing 2"
    $2Path = "$InstallSource\Folder2\file.msi"
    $processInfo = New-Object System.Diagnostics.ProcessStartInfo "msiexec.exe"
    $processInfo.arguments = "/i `"$2Path`" /qr ARGUMENTS"
    $processMSI = New-Object System.Diagnostics.Process
    $processMSI.StartInfo = $processInfo
    # Write-host $ProcessInfo.arguments
    $processMSI.Start() | Out-Null
    $processMSI.WaitforExit()

    if ($processMSI.ExitCode -ne 0) {
        Write-Host "The Installer generated error code:" $processMSI.ExitCode "Exiting!"
        exit
    }
}

# Install 3
if (($choice -eq 3) -or ($choice -eq 5)){
    Write-Host "Installing 3"
    $3Path = "$InstallSource\Folder3\file.exe"
    $processInfo = New-Object System.Diagnostics.ProcessStartInfo $3Path
    $processInfo.arguments = "/S /v`" ARGUMENTS`""
    $processEXE = New-Object System.Diagnostics.Process
    $processEXE.StartInfo = $processInfo
    $processEXE.Start() | Out-Null
    $processEXE.WaitforExit()

    if ($processEXE.ExitCode -ne 0) {
        Write-Host "The Installer generated error code:" $processEXE.ExitCode "Exiting!"
        exit
    }
}

# Install 4
if (($choice -eq 4) -or ($choice -eq 5)){
    Write-Host "Checking for the Desktop-Experience Feature"
    $DEStatus = Get-WindowsFeature Desktop-Experience
    if( $DEStatus.Installed -ne "True" ) {
        Write-Host "Installing Desktop-Experience Feature"
        Import-Module ServerManager
        Add-WindowsFeature -Name Desktop-Experience
    }
    Write-Host "Installing 4"
    $4Path = "$InstallSource\Folder4\file.exe"
    $processInfo = New-Object System.Diagnostics.ProcessStartInfo $4Path
    $processInfo.arguments = "ARGUMENTS"
    $processEXE = New-Object System.Diagnostics.Process
    $processEXE.StartInfo = $processInfo
    $processEXE.Start() | Out-Null
    $processEXE.WaitforExit()

    if ($processEXE.ExitCode -ne 0) {
        Write-Host "The Installer generated error code:" $processEXE.ExitCode "Exiting!"
        exit
    }

    # Install 5
    Write-Host "Installing 5"
    $5Path = "$InstallSource\Folder5\file.exe"
    $processInfo = New-Object System.Diagnostics.ProcessStartInfo $5Path
    $processInfo.arguments = "ARGUMENTS"
    $processEXE = New-Object System.Diagnostics.Process
    $processEXE.StartInfo = $processInfo
    $processEXE.Start() | Out-Null
    $processEXE.WaitforExit()

    if ($processEXE.ExitCode -ne 0) {
        Write-Host "The Installer generated error code:" $processEXE.ExitCode "Exiting!"
        exit
    }
}

# Install 6
if (($choice -eq 3) -or ($choice -eq 5)){
    Write-Host "Installing 6"
    $6Path = "$InstallSource\Folder6\file.exe"
    $processInfo = New-Object System.Diagnostics.ProcessStartInfo $6Path
    $processInfo.arguments = "ARGUMENTS"
    $processEXE = New-Object System.Diagnostics.Process
    $processEXE.StartInfo = $processInfo
    $processEXE.Start() | Out-Null
    $processEXE.WaitforExit()

    if ($processEXE.ExitCode -ne 0) {
        Write-Host "The Installer generated error code:" $processEXE.ExitCode "Exiting!"
        exit
    }
}

# Install 7
if (($choice -eq 4) -or ($choice -eq 5)){
    Write-Host "Installing 7"
    $7Path = "$InstallSource\Folder7\file.exe"
    $processInfo = New-Object System.Diagnostics.ProcessStartInfo $7Path
    $processInfo.arguments = "ARGUMENTS"
    $processEXE = New-Object System.Diagnostics.Process
    $processEXE.StartInfo = $processInfo
    $processEXE.Start() | Out-Null
    $processEXE.WaitforExit()

    if ($processEXE.ExitCode -ne 0) {
        Write-Host "The Installer generated error code:" $processEXE.ExitCode "Exiting!"
        exit
    }
}

采用 TheMadTechnician 的代码,我对其进行了简化并运行它以查看发生了什么.下面是测试代码:

Taking TheMadTechnician's code, I simplified it and ran it to see what was happening. Here is the test code:

$App1 = "Write-host App1"
$App2 = "Write-host App2"
$App3 = "Write-host App3"
$App4 = "Write-host App4"
$App5 = "Write-host App5"
$App6 = "Write-host App6"
$App7 = "Write-host App7"

# Main Level Menu Choices
$Main_Prompt = '
[1] Choice1
[2] Choice2
[3] Choice3
[4] Choice4
[5] Choice5
[q] Quit
'

switch (Read-Host $Main_Prompt)
    {
        {$_ -eq 1 -or $_ -eq 5} {$ToInstall += $App1}
        {$_ -eq 2 -or $_ -eq 5} {$ToInstall += $App2}
        {$_ -eq 3 -or $_ -eq 5} {$App3,$App4|%{If(!($ToInstall -contains $_)){$ToInstall += $_}}}
        {$_ -eq 4 -or $_ -eq 5} {$App5,$App6,$App7|%{If(!($ToInstall -contains $_)){$ToInstall += $_}}}
        {$_ -ieq "q"} {Write-host "Exiting!";Exit}
    }

ForEach($App in ($ToInstall | Select -Unique)){
    Invoke-Expression $App
}

这是结果(在代码块中,因为我还不能发布图片):

Here is the result (in a code block because I can't post images yet):

PS C:\temp> .\test.ps1

[1] Choice1
[2] Choice2
[3] Choice3
[4] Choice4
[5] Choice5
[q] Quit
: 5
App1Write-host App2Write-host App3Write-host App4Write-host App5Write-host App6Write-host App7
PS C:\temp>

似乎块执行了第一个命令,但随后只是将其余命令打印到屏幕上.我对此非常不适应.

It appears that the block executes the first command, but then just prints the rest of them to the screen. I'm very much out of my element with this.

推荐答案

我认为你正在寻找的东西最好这样做(将代码从 158 行减少到 43 行)...

I think what you are looking for would be better done like this (reduces code from 158 lines to 43)...

创建一个空数组,并定义您的应用程序路径(或将其移动到开关,当您看到开关时这可能对您更有意义).在开关中创建定义应用程序标题和该应用程序安装程序路径的对象.然后执行 ForEach 循环,选择唯一对象并安装它们:

Create an empty array, and define your application paths (or move that to the switch, which may make more sense for you when you see the switch). In the switch create objects that define the title of the application, and the path to the installer for that application. Then do a ForEach loop that selects unique objects and installs them:

$ToInstall = @()
$App1 = [PSCustomObject]@{Name="App1 Name";Path="$InstallSource\Folder1\file.msi";Args="/I ""$InstallSource\Folder1\file.msi"" /qn-!"}
$App2 = [PSCustomObject]@{Name="App2 Name";Path="$InstallSource\Folder2\file.msi";Args="/I ""$InstallSource\Folder2\file.msi"" /qb"}
$App3 = [PSCustomObject]@{Name="App3 Name";Path = "$InstallSource\Folder3\file.msi";Args="/I ""$InstallSource\Folder3\file.msi"" /qn"}
$App4 = [PSCustomObject]@{Name="App4 Name";Path = "$InstallSource\Folder4\file.msi";Args="/I ""$InstallSource\Folder4\file.msi"" /qb-!"}
$App5 = [PSCustomObject]@{Name="App5 Name";Path = "$InstallSource\Folder5\file.msi";Args="/I ""$InstallSource\Folder5\file.msi"" /qn"}
$App6 = [PSCustomObject]@{Name="App6 Name";Path = "$InstallSource\Folder6\file.msi";Args="/I ""$InstallSource\Folder6\file.msi"" /qb-! REBOOT=ReallySuppress"}
$App7 = [PSCustomObject]@{Name="App7 Name";Path = "$InstallSource\Folder7\file.msi";Args="/I ""$InstallSource\Folder7\file.msi"" /qr"}

# Main Level Menu Choices
switch (Read-Host $Main_Prompt)
    {
        {$_ -eq 1 -or $_ -eq 5} {$ToInstall += $App1}
        {$_ -eq 2 -or $_ -eq 5} {$ToInstall += $App2}
        {$_ -eq 3 -or $_ -eq 5} {$App3,$App6,$App7|%{If(!($ToInstall -contains $_)){$ToInstall += $_}}}
        {$_ -eq 4 -or $_ -eq 5} {$App4,$App6,$App7|%{If(!($ToInstall -contains $_)){$ToInstall += $_}}}
        {!($_ -ieq "q")} {$ToInstall += $App5}
        {$_ -ieq "q"} {Write-host "Exiting!";Exit}
    }


# Install each app selected

ForEach($App in ($ToInstall |Sort Name)){
    Write-Host $App.Name
    if (Test-Path $App.Path) {
        If($App.Name -eq "App3 Title"){Do stuff to stop service}
        $processInfo = New-Object System.Diagnostics.ProcessStartInfo "msiexec.exe"
        $processInfo.arguments = $App.args
        $processMSI = New-Object System.Diagnostics.Process
        $processMSI.StartInfo = $processInfo
        $processMSI.Start() | Out-Null
        $processMSI.WaitforExit()

        if ($processMSI.ExitCode -ne 0) {
            Write-Host "The Installer generated error code:" $processMSI.ExitCode "Exiting!"
            exit
        }
    }
    Else {
        Write-host "Installer does not exist. Exiting!"
        exit
    }
}

将对象的创建移至切换之前,插入代码以检查指定应用程序安装时的服务.

Moved creation of objects to before the switch, inserted code to check service on specified application install.

Edit2: 更新了 $processInfo.arguments = 行,并修复了 $App3-$App7 行.还重新做了如何将应用程序添加到 $ToInstall 数组以避免在 ForEach 循环中重复和排序安装顺序.

Updated $processInfo.arguments = line, and fixed $App3-$App7 lines. Also re-did how apps are added to the $ToInstall array to avoid duplicates and sorted installation order in the ForEach loop.

这篇关于创建一个 for 循环来整合 powershell 菜单驱动的脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆