如何在Azure DevOps中用PowerShell正确打印Unicode字符串
问题描述
我需要将标准输出(stdout)记录到Azure DevOps任务的日志中。以下是我的PowerShell脚本片段:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "msiexec.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = "/i `"<<my-msi-file>>`" REBOOT=ReallySuppress /L*v+ $logFile /qn" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() Write-Host "stdout: $stdout"
我能获取到输出,但显示异常,无法正常复制粘贴,大致显示为:
Example text
如何让文本正常显示为“Example text”?
补充说明:
若要在标准输出中获取错误文本,只需将<<my-msi-file>>替换为不存在的文件名,例如c:\dev\null\nofile.msi。
解决方案
这是编码不匹配导致的问题:msiexec.exe的标准输出采用**UTF-16LE(Unicode)**编码,但PowerShell默认用UTF-8解析输出,使得每个字符间被插入空字节,最终显示为带间隔符号的乱码。
你可以通过两种方式修复:
方式1:读取时指定编码
替换脚本中读取输出的代码:
# 替换原有的 $stdout = $p.StandardOutput.ReadToEnd() $stdout = [Console]::OutputEncoding.GetString($p.StandardOutput.BaseStream.ToArray())
方式2:配置ProcessStartInfo的输出编码
在创建ProcessStartInfo时直接指定编码:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "msiexec.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false # 添加编码设置,匹配msiexec的输出编码 $pinfo.StandardOutputEncoding = [System.Text.Encoding]::Unicode $pinfo.Arguments = "/i `"<<my-msi-file>>`" REBOOT=ReallySuppress /L*v+ $logFile /qn" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() Write-Host "stdout: $stdout"
两种方法都能让输出正常显示,解决乱码和无法复制的问题。
内容的提问来源于stack exchange,提问作者ffonz
相关产品推荐
相关产品推荐

