如何在PowerShell中捕获ProcessStartInfo标准输出并做字符串比较
解决msiexec输出字符串比较失败的问题
问题根源分析
- 空值判断失效:
$p.StandardOutput.ReadToEnd()即使没有输出,返回的也是**空字符串("")**而非$null,再经过Out-String处理后依然是空字符串,所以用$stdout -eq $null永远不会成立。 - 特殊格式字符串匹配失败:你看到的每个字母间带空格的输出,是因为msiexec的错误输出采用UTF-16LE(Unicode)编码,但PowerShell默认用系统ANSI编码读取,导致字符解析错乱,出现多余空格。
具体解决步骤
1. 正确判断空输出
用以下两种方式替代$stdout -eq $null:
- 检查空字符串或null:
[string]::IsNullOrEmpty($stdout) - 直接匹配空字符串:
$stdout -eq ''
2. 修正输出编码,解决字符串格式错乱
在创建ProcessStartInfo时,指定StandardOutputEncoding和StandardErrorEncoding为UTF-16LE(对应[System.Text.Encoding]::Unicode),确保正确解析msiexec的输出。
修改后的完整代码
$pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = 'msiexec' # 指定编码为UTF-16LE,匹配msiexec的输出编码 $pinfo.StandardOutputEncoding = [System.Text.Encoding]::Unicode $pinfo.StandardErrorEncoding = [System.Text.Encoding]::Unicode $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = "/x {22AD1D41-EDA0-4387-BF16-9045CE734FAD} /quiet /norestart /l*v `"C:\temp\msi123_MSI_UNINSTALL.log`"" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() # 无需再用Out-String,ReadToEnd()已经返回正确格式的字符串,Trim()去除首尾空白 $stdout = $p.StandardOutput.ReadToEnd().Trim() $stderr = $p.StandardError.ReadToEnd().Trim()
3. 正确匹配目标字符串
编码修正后,直接用正常的字符串进行比较即可:
$targetMsg = "This action is only valid for products that are currently installed." if ($stdout -eq $targetMsg -or $stderr -eq $targetMsg) { # 处理未安装产品的情况 Write-Host "目标产品未安装,无法执行卸载操作" }
额外提示
- msiexec的错误信息有时会输出到
stderr而非stdout,建议同时检查两个输出流 - 使用
Trim()可以去除输出中可能存在的首尾换行符或空格,避免因多余空白导致匹配失败
内容的提问来源于stack exchange,提问作者Bbb
相关产品推荐
相关产品推荐

