You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell GUI无人值守软件安装的状态显示优化问题

解决PowerShell GUI安装状态显示混乱的问题

我来帮你搞定这个状态显示的问题~你的脚本目前有两个核心问题:一是Start-Process默认是异步执行的,脚本不会等软件安装/卸载完成就直接更新文本框;二是没有添加换行符,导致所有状态文本挤在了一起。

下面是修复后的完整脚本,同时我把关键修改点列在前面,方便你理解:

关键修改点

  • 给Start-Process添加-Wait参数,强制等待安装/卸载进程结束后再更新状态
  • 每次更新文本框时,通过"n"`添加换行符,让每条状态单独占一行
  • 进程完成后追加对应的状态标识(安装完成加...OK,卸载完成加...Done)
  • 抽离了重复的软件状态检测逻辑,写成一个小函数,让代码更简洁
  • 给结果文本框添加了垂直滚动条,方便查看多条状态记录
  • 加入$ResultsTextBox.Refresh(),确保状态文本实时显示,不会等到所有操作完成才一起更新

修复后的完整脚本

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 封装软件状态检测函数,避免重复代码
function Get-SoftwareInstalledStatus {
    param([string]$SoftwareName)
    return Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* -ErrorAction SilentlyContinue | 
           Where-Object {$_.DisplayName -like "*$SoftwareName*"}
}

# 软件列表:统一管理,后续新增软件只需加一行
$softwareList = @(
    @{Name = "7-Zip"; InstallerPath = "$PSScriptRoot\software\7z1900-x64.msi"; UninstallCode = "{23170F69-40C1-2702-1900-000001000000}"},
    @{Name = "Notepad++"; InstallerPath = "$PSScriptRoot\software\npp.7.8.1.Installer.x64.exe"; UninstallPath = "${env:ProgramFiles}\Notepad++\uninstall.exe"},
    @{Name = "Visual Studio Code"; InstallerPath = "$PSScriptRoot\software\VSCodeSetup-x64-1.40.2.exe"; UninstallPath = "${env:ProgramFiles}\Microsoft VS Code\unins000.exe"}
)

# 创建主窗体
$Form = New-Object System.Windows.Forms.Form
$Form.Width = 500
$Form.Height = 500
$Form.Text = 'Install Software'
$Font = New-Object System.Drawing.Font("Verdana",10)
$Form.Font = $Font

# 结果文本框:优化显示,添加垂直滚动条
$ResultsTextBox = New-Object System.Windows.Forms.TextBox
$ResultsTextBox.Location = New-Object System.Drawing.Size(200,30)
$ResultsTextBox.Size = New-Object System.Drawing.Size(250,350)
$ResultsTextBox.Multiline = $true
$ResultsTextBox.ScrollBars = "Vertical"
$ResultsTextBox.Text = "Make your selections on the left`n"
$Form.Controls.Add($ResultsTextBox)

# 批量创建复选框,减少重复代码
$yPos = 30
foreach ($software in $softwareList) {
    $status = Get-SoftwareInstalledStatus -SoftwareName $software.Name
    $checkbox = New-Object System.Windows.Forms.CheckBox
    $checkbox.Location = New-Object System.Drawing.Size(30, $yPos)
    $checkbox.Size = New-Object System.Drawing.Size(150,20)
    $checkbox.Text = $software.Name
    $checkbox.Checked = ($status -ne $null)
    $checkbox.Tag = $software  # 把软件信息存到Tag属性,方便后续调用
    $Form.Controls.Add($checkbox)
    $yPos += 25
}

# OK按钮点击事件
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(130,400)
$OKButton.Size = New-Object System.Drawing.Size(100,40)
$OKButton.Text = "OK"
$OKButton.Add_Click({
    foreach ($checkbox in $Form.Controls | Where-Object {$_.GetType().Name -eq "CheckBox"}) {
        $software = $checkbox.Tag
        $status = Get-SoftwareInstalledStatus -SoftwareName $software.Name

        # 处理安装逻辑
        if ($checkbox.Checked -and $status -eq $null) {
            $ResultsTextBox.Text += "Installing $($software.Name)... "
            $ResultsTextBox.Refresh()  # 强制刷新,即时显示当前状态
            if ($software.InstallerPath.EndsWith(".msi")) {
                Start-Process -FilePath $software.InstallerPath -ArgumentList "/passive" -Wait -NoNewWindow
            } else {
                Start-Process -FilePath $software.InstallerPath -ArgumentList "/S" -Wait -NoNewWindow
            }
            $ResultsTextBox.Text += "OK`n"
        }

        # 处理卸载逻辑
        if (-not $checkbox.Checked -and $status -ne $null) {
            $ResultsTextBox.Text += "Removing $($software.Name)... "
            $ResultsTextBox.Refresh()
            if ($software.UninstallCode) {
                Start-Process -FilePath "MsiExec.exe" -ArgumentList "/x$($software.UninstallCode) /passive" -Wait -NoNewWindow
            } else {
                Start-Process -FilePath $software.UninstallPath -ArgumentList "/S" -Wait -NoNewWindow
            }
            $ResultsTextBox.Text += "Done`n"
        }
    }
})
$Form.Controls.Add($OKButton)

# Close按钮
$CloseButton = New-Object System.Windows.Forms.Button
$CloseButton.Location = New-Object System.Drawing.Size(255,400)
$CloseButton.Size = New-Object System.Drawing.Size(100,40)
$CloseButton.Text = "Close"
$CloseButton.Add_Click({$Form.Close()})
$Form.Controls.Add($CloseButton)

# 激活窗体
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

额外说明

我把软件信息整理成了统一的列表,后续添加新软件只需要在$softwareList里追加一行配置即可,不用重复编写复选框和判断逻辑,维护起来更方便。

内容的提问来源于stack exchange,提问作者aristosv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:00:43