[英]PowerShell encoding issue when storing cmdlet response in variable
I've spent the last hour or so trying to figure out what's happening here, and I simply can't figure out the cause, nor have I accidentally stumbled upon a workaround.我花了最后一个小时左右试图弄清楚这里发生了什么,但我根本无法找出原因,也没有偶然发现解决方法。
When I run winget upgrade
the data returned is correctly encoded:当我运行
winget upgrade
时,返回的数据已正确编码:
Yet if I store the response of winget upgrade in a variable ( $winget = winget upgrade; $winget;
), some characters break, and it seems like an encoding issue:然而,如果我将 winget upgrade 的响应存储在一个变量中(
$winget = winget upgrade; $winget;
),一些字符会中断,这似乎是一个编码问题:
cmdlets like this will always return strings to PowerShell, so I guess assigning the response to the variable is applying some default text encoding, perhaps from my PowerShell profile?像这样的 cmdlet 将始终将字符串返回到 PowerShell,所以我想将响应分配给变量正在应用一些默认文本编码,可能来自我的 PowerShell 配置文件? I've tried casting most of the common codes on the variable, but it ends up breaking the data entirely.
我已经尝试在变量上强制转换大多数常见代码,但它最终完全破坏了数据。
I've even dumped the data out in every possible encoding type and they're all broken:我什至以每种可能的编码类型将数据转储出来,它们都被破坏了:
winget upgrade | Out-File -FilePath C:\tmp\test1.txt -Encoding ascii
winget upgrade | Out-File -FilePath C:\tmp\test3.txt -Encoding default
winget upgrade | Out-File -FilePath C:\tmp\test4.txt -Encoding string
winget upgrade | Out-File -FilePath C:\tmp\test5.txt -Encoding unicode
winget upgrade | Out-File -FilePath C:\tmp\test7.txt -Encoding utf32
winget upgrade | Out-File -FilePath C:\tmp\test8.txt -Encoding utf7
winget upgrade | Out-File -FilePath C:\tmp\test9.txt -Encoding utf8
I've managed to affect the faulty characters by re-encoding the string, bt hasn't fix the issue:我已经设法通过重新编码字符串来影响错误字符,bt 没有解决问题:
$originalBytes = [Text.Encoding]::Default.GetBytes('Microsoft Visual C++ 2013 Redistributable (x6')
[Text.Encoding]::Utf8.GetString($originalBytes)
Credit to @JosefZ for sharing the solution, which can be found here: How to configure the encoding for Powershell console?感谢@JosefZ 分享解决方案,可在此处找到: 如何配置 Powershell 控制台的编码?
This is the output of [console]::OutputEncoding
:这是
[console]::OutputEncoding
:
PS C:\> [console]::OutputEncoding
IsSingleByte : True
BodyName : ibm850
EncodingName : Western European (DOS)
HeaderName : ibm850
WebName : ibm850
WindowsCodePage : 1252
IsBrowserDisplay : False
IsBrowserSave : False
IsMailNewsDisplay : False
IsMailNewsSave : False
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 850
This is the output of [Console]::Out
:这是
[Console]::Out
的 output :
PS C:\> [Console]::Out
Encoding FormatProvider NewLine
-------- -------------- -------
System.Text.SBCSCodePageEncoding en-GB ...
Changing my console output to UTF-8 using [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
has solved the issue.使用
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
将我的控制台 output 更改为 UTF-8 解决了这个问题。
Now, when I store the cmdlet response in a variable, all is right in the world:现在,当我将 cmdlet 响应存储在变量中时,一切正常:
PS C:\> [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
PS C:\> $winget = winget upgrade
PS C:\> $winget
Name Id Version Available Source
-----------------------------------------------------------------------------------------------------------------------
Signal OpenWhisperSystems.Signal 5.20.0 5.23.1 winget
Cisco Webex Meetings Cisco.CiscoWebexMeetings 41.9.5 41.12.2.15 winget
Audacity Audacity.Audacity 3.0.4 3.1.2 winget
Docker Desktop Docker.DockerDesktop 4.1.1 4.2.0 winget
Git Git.Git 2.33.0.2 2.34.0 winget
MongoDB Compass MongoDB.Compass.Full 1.28.4 1.29.4.0 winget
TeamViewer TeamViewer.TeamViewer 15.22.3 15.23.9 winget
Visual Studio Community 2019 Microsoft.VisualStudio.2019.Community 16.11.3 16.11.7 winget
Insomnia Insomnia.Insomnia 2021.5.3 2021.6.0 winget
Microsoft Visual C++ 2013 Redistributable (x6… Microsoft.VC++2013Redist-x64 12.0.30501.0 12.0.40664.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x64 14.29.30133.0 14.29.30135.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x86 14.29.30133.0 14.29.30135.0 winget
Node.js LTS OpenJS.NodeJS.LTS 14.17.6 16.13.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x64 14.28.29914.0 14.29.30135.0 winget
ScreenToGif NickeManarin.ScreenToGif 2.33.1 2.34.1 winget
MongoDB MongoDB.Server 5.0.2 5.1.0 winget
AWS Command Line Interface Amazon.AWSCLI 2.2.46.0 2.3.7.0 winget
Chrome Remote Desktop Host Google.ChromeRemoteDesktop 92.0.4515.41 96.0.4664.39 winget
Microsoft Visual C++ 2013 Redistributable (x8… Microsoft.VC++2013Redist-x86 12.0.30501.0 12.0.40664.0 winget
19 upgrades available.
I know you said replacing the characters is not an option.我知道你说替换字符不是一种选择。 I'm curious to see what you come up with.
我很好奇你想出了什么。 For the rest of us, here is a little code that will turn the output of
winget upgrade
into usable object.对于我们的 rest,这里有一个小代码,它将把
winget upgrade
的 output 变成可用的 object。
(winget upgrade) -replace 'ΓǪ|…|…',' ' | ForEach-Object {
if($_ -match '(.+?)\s{2,}(.+?)\s+(\S+)\s+(\S+)\s+(\S+)$'){
$Matches[1..5] -join '|'
}
} | ConvertFrom-Csv -Delimiter '|'
Here is the default output in list form这是列表形式的默认 output
Name : Cisco Webex Meetings
Id : Cisco.CiscoWebexMeetings
Version : 41.9.5
Available : 41.12.2.15
Source : winget
Name : Discord
Id : Discord.Discord
Version : 0.0.309
Available : 1.0.9003
Source : winget
Name : GitHub Desktop
Id : GitHub.GitHubDesktop
Version : 2.9.0
Available : 2.9.4
Source : winget
And when using Format-Table
并且在使用
Format-Table
时
Name Id Version Available Source
---- -- ------- --------- ------
Visual Studio Community 2019 Microsoft.VisualStudio.2019.Community 16.10.31410.357 16.11.7 winget
Cisco Webex Meetings Cisco.CiscoWebexMeetings 41.9.5 41.12.2.15 winget
Discord Discord.Discord 0.0.309 1.0.9003 winget
I've tested in 5.1, 7.2, ISE, and Visual Studio Code.我在 5.1、7.2、ISE 和 Visual Studio Code 中进行了测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.