我正在嘗試使用 Powershell 根據命令“wsl --list”的輸出保存一些環境變數,當我除錯這段代碼時,它似乎按預期流動但是當我檢查我的環境變數時,我無法找到預期的鍵和值。
當我對任何其他硬編碼值使用相同的 SetEnvironmentVariable 方法時,它似乎有效。$distroName 上的 Write-Host 也會產生預期的字串,所以老實說我對此感到迷茫。任何幫助,將不勝感激!這是我的代碼:
$wslListOutput = wsl --list
((Get-ChildItem env:*).Name | Select-String -Pattern "(SINDAGAL_INIT_DISTRO_([a-zA-Z=])*)|SINDAGAL_DEFAULT_DISTRO")
foreach ($line in $wslListOutput)
{
$lineIsEmpty = ("" -eq $line) -or ([string]::IsNullOrWhiteSpace($line))
$Introline = $line -eq "Windows Subsystem for Linux Distributions:"
if($lineIsEmpty -or $Introline){ continue }
if($line -Match "(([a-zA-Z]*) ([(Default)])*)"){
$distroName = ($line -split ' ',2)[0]
[System.Environment]::SetEnvironmentVariable("SINDAGAL_DEFAULT_DISTRO",$distroName)
} else{
$distroName = $line.ToUpper()
$variablePath = "Env:SINDAGAL_INIT_DISTRO_${distroName}"
[System.Environment]::SetEnvironmentVariable("SINDAGAL_INIT_DISTRO_${distroName}",$true)
}
}
# Cannot see the variables which are supposed to be set in here at all
((Get-ChildItem env:*).Name)
我的 wsl --list 輸出:
┖[~]> wsl --list
Windows Subsystem for Linux Distributions:
Debian (Default)
Alpine
uj5u.com熱心網友回復:
這是編碼問題。的重定向輸出wsl是 UTF-16 LE 編碼,PowerShell 無法識別(從 PS 7.1.5 開始)。它試圖將輸出解釋為 UTF-8,因此我們最終得到了嵌入\0字符(對于 UTF-16 LE 編碼的 ASCII 字符,每第二個位元組為 0)。在呼叫 時SetEnvironmentVariable,這些會導致字串被剪切,因為 API 需要以空字符結尾的字串。
解決方法
從 PS 7.x 開始,設定似乎就足夠了
[Console]::OutputEncoding = [Text.Encoding]::Unicode
在啟動wsl行程之前。之后應該恢復編碼。有關更深入的資訊和cmdlet,請參閱此答案,該Invoke-WithEncodingcmdlet 可自動執行臨時更改和恢復編碼的程序。
作為另一種解決方法,我們可以Start-Process將輸出按原樣重定向到檔案,然后使用Get-Content強制 UTF-16 LE(又名“Unicode”)編碼讀取檔案。我們還使用引數-raw將檔案作為單個字串讀取,因為 WSL 會寫入奇怪的行分隔符,這會在 PowerShell 嘗試拆分輸入時混淆。最好使用-split運算子自行拆分字串。
正如評論者所建議的那樣,我還添加了“machine”引數,SetEnvironmentVariable以便在 PowerShell 會話結束時變數值將保持不變。請注意,這在運行腳本時需要管理員權限。
# Redirect WSL output to temp file, which keeps the UTF-16 encoding intact
$tempFilePath = (New-TemporaryFile).FullName
Start-Process -FilePath wsl -ArgumentList '--list' -RedirectStandardOutput $tempFilePath -NoNewWindow -Wait
# Read temp file with forced UTF-16 LE encoding
$wslListOutput = Get-Content $tempFilePath -Raw -Encoding unicode
# Split on new lines ("\r*" because WSL writes duplicate "\r" chars)
$wslLines = $wslListOutput -split "\r*\n"
foreach ($line in $wslLines)
{
$lineIsEmpty = ("" -eq $line) -or ([string]::IsNullOrWhiteSpace($line))
$Introline = $line -eq "Windows Subsystem for Linux Distributions:"
if($lineIsEmpty -or $Introline){ continue }
if($line -Match "(([a-zA-Z]*) ([(Default)])*)"){
$distroName = ($line -split ' ',2)[0]
[System.Environment]::SetEnvironmentVariable("SINDAGAL_DEFAULT_DISTRO",$distroName,"machine")
} else{
$distroName = $line.ToUpper()
$variablePath = "Env:SINDAGAL_INIT_DISTRO_${distroName}"
[System.Environment]::SetEnvironmentVariable("SINDAGAL_INIT_DISTRO_${distroName}",$true,"machine")
}
}
Get-ChildItem env:SINDAGAL_*
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/323336.html
