Reputation: 23
I'm attempting to save some environment variables based on the output of the command "wsl --list" using Powershell, when I debug this code it seems to be flowing as expected however when I inspect my environment variables I'm unable to find the expected keys and values.
When I use the same SetEnvironmentVariable method with any other hardcoded value it seems to work. Write-Host on $distroName results in the expected string too so I'm honestly lost on this. Any help would be appreciated! Here is my code:
$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)
my wsl --list output:
┖[~]> wsl --list
Windows Subsystem for Linux Distributions:
Debian (Default)
Alpine
Upvotes: 2
Views: 1180
Reputation: 27756
This is an encoding issue. Redirected output of wsl
is UTF-16 LE encoded, which is not automatically recognized by PowerShell (as of PS 7.1.5). Instead it always interprets the output using the encoding stored in [Console]::OutputEncoding
, which on Windows defaults to the given system's legacy OEM code page (e.g. 437 on US-English systems).
As UTF-16 is a two-byte encoding we typically end up with embedded \0
characters (code points below 256, such as the ASCII character set). These cause the string to be clipped, when calling SetEnvironmentVariable
, because the API expects null-terminated strings.
Set [Console]::OutputEncoding
to match the output encoding of the process, before launching it and restore the original encoding afterwards.
$oldEncoding = [Console]::OutputEncoding
[Console]::OutputEncoding = [Text.Encoding]::Unicode # on Windows: UTF-16 LE
$wslListOutput = wsl --list
[Console]::OutputEncoding = $oldEncoding
Another common output encoding used by some programs is [Text.Encoding]::UTF8
.
See this answer for more in-depth information and an Invoke-WithEncoding
cmdlet, which automates the process of temporarily changing and restoring the encoding.
Upvotes: 3