Get-Package返回多结果时,如何循环卸载所有匹配程序?
批量卸载ESET产品的PowerShell脚本问题修正
问题场景
运行PowerShell脚本卸载ESET时,Get-Package返回多个匹配结果,脚本会将多个产品的信息合并成单字符串,导致卸载命令执行失败。现有脚本无法循环处理每个独立的ESET产品。
现有问题代码:
# Uninstall apps $AppNames = @("eset ") $AppNames | ForEach-Object { $Package = (Get-Package -Name *$_*) | Tee-Object -FilePath $LogPath if ( $Package.ProviderName -eq "msi" ) { $Guid = $Package.FastPackageReference | Tee-Object -FilePath $LogPath -Append $Name = $Package.Name | Tee-Object -FilePath $LogPath -Append $Version = $Package.Version | Tee-Object -FilePath $LogPath -Append "Uninstalling $Name $Version" | Tee-Object -FilePath $LogPath -Append $Process = Start-Process msiexec.exe -ArgumentList "/x$Guid /quiet /norestart" -Wait -PassThru echo "Exit code: " | Tee-Object -FilePath $LogPath -Append $Process | Select ExitCode -ExpandProperty ExitCode | Tee-Object -FilePath $LogPath -Append } }
执行后错误输出示例:
Uninstalling ESET Remote Administrator Agent ESET Endpoint Antivirus 6.5.522.0 10.1.2050.0
问题原因
当Get-Package返回多个对象时,直接访问$Package.ProviderName、$Package.Name等属性会返回所有对象对应属性值组成的数组,字符串拼接时数组元素会自动用空格连接,导致卸载命令中的$Guid也是数组,最终msiexec命令无效。
修正方案
在获取到多个Package对象后,添加一层循环逐个处理每个ESET产品:
# Uninstall apps $AppNames = @("eset") $AppNames | ForEach-Object { # 获取所有匹配的ESET包,输出到日志 $Packages = Get-Package -Name *$_* | Tee-Object -FilePath $LogPath # 循环处理每个单独的Package对象 $Packages | ForEach-Object { $CurrentPackage = $_ if ($CurrentPackage.ProviderName -eq "msi") { $Guid = $CurrentPackage.FastPackageReference $Name = $CurrentPackage.Name $Version = $CurrentPackage.Version # 记录当前卸载的产品信息到日志 "Uninstalling $Name $Version" | Tee-Object -FilePath $LogPath -Append "Package GUID: $Guid" | Tee-Object -FilePath $LogPath -Append # 执行静默卸载命令 $Process = Start-Process msiexec.exe -ArgumentList "/x$Guid /quiet /norestart" -Wait -PassThru # 记录卸载退出码 "Exit code for $Name : $($Process.ExitCode)" | Tee-Object -FilePath $LogPath -Append } } }
关键修改点
- 将
$Package改为$Packages,明确表示这是多对象集合 - 添加
$Packages | ForEach-Object {}内部循环,单独处理每个ESET产品包 - 用
$CurrentPackage = $_引用当前单个包对象,避免数组属性拼接问题 - 优化日志记录逻辑,让每个产品的卸载信息更清晰
- 简化退出码获取方式,直接通过
$Process.ExitCode读取
内容的提问来源于stack exchange,提问作者KLEPTOROTH
相关产品推荐
相关产品推荐

