Powershell SetEnvironmentVariable 未按预期设置变量

Powershell SetEnvironmentVariable not setting the variables as expected

我正在尝试使用 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

原因

这是一个编码问题。 wsl 的重定向输出是 UTF-16 LE 编码的,它不会被 PowerShell 自动识别(从 PS 7.1.5 开始)。相反,它总是使用存储在 [Console]::OutputEncoding 中的编码解释输出,在 Windows 上默认为给定系统的旧 OEM 代码页(例如,美国英语系统上的 437)。

由于 UTF-16 是一种双字节编码,我们通常以嵌入的 [=13=] 字符结束(代码点低于 256,例如 ASCII 字符集)。在调用 SetEnvironmentVariable 时,这些会导致字符串被剪裁,因为 API 需要以 null 结尾的字符串。

解决方案

设置[Console]::OutputEncoding以匹配进程的输出编码,然后再启动它并在之后恢复原始编码。

$oldEncoding = [Console]::OutputEncoding
[Console]::OutputEncoding = [Text.Encoding]::Unicode  # on Windows: UTF-16 LE

$wslListOutput = wsl --list

[Console]::OutputEncoding = $oldEncoding

一些程序使用的另一种常见输出编码是[Text.Encoding]::UTF8

有关更深入的信息和 Invoke-WithEncoding cmdlet,请参阅 ,它会自动执行临时更改和恢复编码的过程。