我如何将PowerShell脚本转换成Base64?

4

我一直在努力思考,但无法弄清楚为什么我的代码会失去完整性...

我有以下脚本,我正在尝试将其转换为Base64:

Function Get-Networks { 
    $Network = Get-WmiObject Win32_NetworkAdapterConfiguration | where { $_.MACAddress -notlike $null }  | select Index, Description, IPAddress, DefaultIPGateway, MACAddress | Format-Table Index, Description, IPAddress, DefaultIPGateway, MACAddress     
    $WLANProfileNames = @() 
    $Output = netsh.exe wlan show profiles | Select-String -pattern " : " 
    Foreach ($WLANProfileName in $Output) {     
        $WLANProfileNames += (($WLANProfileName -split ":")[1]).Trim() 
    } 
    $WLANProfileObjects = @() 
    Foreach ($WLANProfileName in $WLANProfileNames) {     
        try {         
            $WLANProfilePassword = (((netsh.exe wlan show profiles name="$WLANProfileName" key=clear | select-string -Pattern "Key Content") -split ":")[1]).Trim()     
        }
        Catch {         
            $WLANProfilePassword = "The password is not stored in this profile"     
        }     
        $WLANProfileObject = New-Object PSCustomobject      
        $WLANProfileObject | Add-Member -Type NoteProperty -Name "ProfileName" -Value $WLANProfileName     
        $WLANProfileObject | Add-Member -Type NoteProperty -Name "ProfilePassword" -Value $WLANProfilePassword     
        $WLANProfileObjects += $WLANProfileObject     
        Remove-Variable WLANProfileObject  
        return $WLANProfileObjects 
    } 
}  
$Networks = Get-Networks 
echo $Networks

最初,我使用以下代码片段来完成它。它会将文件内容读取到一个变量中并进行转换。但我发现,当我将其转换回去后,输出的结果会把所有内容都放在一行上,导致格式混乱。

$Content = Get-Content -Path $FilePath    
$converted = [convert]::ToBase64String([System.Text.encoding]::Unicode.GetBytes($Content))

所以我转而使用以下代码片段,使用文件路径转换它,而不是将内容保存到一个变量中。当我将其转换回来时,很高兴看到它保持了完整性。
[convert]::ToBase64String((Get-Content -path $FilePath -Encoding byte))

但当我试图执行它时,这次它抛出了以下错误,我感到更加困惑了。

畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴牯‽敇⵴浗佩橢捥⁴楗㍮弲敎睴牯䅫慤瑰牥潃普杩牵瑡潩⁼桷牥⁥⁻弤䴮䍁摁牤獥⁳渭瑯楬敫␠畮汬素†⁼敳敬瑣䤠摮硥‬敄捳楲瑰潩Ɱ䤠䅐摤敲獳‬敄慦汵䥴䝐瑡睥祡‬䅍䅃摤敲獳簠䘠牯慭⵴慔汢⁥湉敤ⱸ䐠獥牣灩楴湯‬偉摁牤獥ⱳ䐠晥畡瑬 偉慇整慷ⱹ䴠䍁摁牤獥⁳ഉ␊䱗乁牐景汩乥浡獥㴠⡀ഩ␊畏灴瑵㴠渠瑥桳攮數眠慬桳睯瀠潲楦敬⁳⁼敓敬瑣匭牴湩⁧瀭瑡整湲∠㨠∠਍潆敲捡⡨圤䅌偎潲楦敬慎敭椠伤瑵異⥴ൻ : The term
'畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴牯‽敇⵴浗佩橢捥⁴楗㍮弲敎睴牯䅫慤瑰牥潃普杩牵瑡潩⁼桷牥⁥⁻弤䴮䍁摁牤獥⁳渭瑯楬敫␠畮汬素†⁼敳敬瑣䤠摮硥‬敄捳楲瑰潩Ɱ䤠䅐摤敲獳‬敄慦汵䥴䝐瑡睥祡‬䅍䅃摤敲獳簠䘠牯慭⵴慔汢⁥湉敤ⱸ䐠獥牣灩楴湯‬偉摁牤獥ⱳ䐠晥畡瑬偉慇整慷ⱹ䴠䍁摁牤獥⁳ഉ␊䱗乁牐景汩乥浡獥㴠⡀ഩ␊畏灴瑵㴠渠瑥桳攮數眠慬桳睯瀠潲楦敬⁳⁼敓敬瑣匭牴湩⁧瀭瑡整湲∠㨠∠਍潆敲捡⡨圤䅌偎潲楦敬慎敭椠伤瑵異⥴ൻ' is not recognized
as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ 畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴牯‽敇⵴浗佩橢捥⁴楗㍮弲敎睴牯䅫慤瑰牥潃普杩牵瑡潩⁼桷牥⁥⁻弤䴮䍁摁牤獥⁳渭瑯楬敫␠畮汬素†⁼敳敬瑣䤠摮 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (畆据楴湯䜠瑥中瑥潷歲⁳ൻ␊敎睴...圤䅌偎潲楦敬慎敭椠伤瑵異⥴ൻ:String) [], CommandNotFoundException

我该如何编写一个简单的脚本将这个文件转换为base64格式,以便我可以正确地执行它?


看起来像是编码故障。您可能需要使用代码的保存到文件部分和各种编码选项进行测试。 - Lee_Dailey
3
如果你担心失去格式,可以继续使用当前有效的方法(获取字节然后转换为b64),但在Get-Content命令中加入-Raw开关。 - Santiago Squarzon
是的,我进行了更多的研究并成功找到了解决方案。最终我使用了以下代码:$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8))) - I am Jakoby
2个回答

5
为了补充您自己的有效解决方案,这里提供一些背景信息:
  • Base64编码是一种将任意字节数据编码成ASCII字符串的编码方式,因此如果要对字符串进行编码,就需要决定它作为字节数组的具体编码。

  • 在您最初的尝试中(以及您有效的解决方案中),您正确地基于输入字符串的UTF-16LE编码所组成的字节来获取Base64编码的字符串[System.Text.Encoding]::Unicode.GetBytes(...)),因为这是Windows PowerShell CLI(powershell.exe)/ PowerShell (Core) 7+ CLI(pwsh)在传递给其-EncodedCommand参数的参数中所需的。

    • 术语说明:在.NET和PowerShell中,这个具体的Unicode编码对于抽象的Unicode标准命名不合适(.NET中的[System.Text.Encoding]::Unicode,PowerShell各种文件处理cmdlet中的-Encoding Unicode
  • 您最初尝试的问题是使用Get-Content 没有使用-Raw开关,正如Santiago Squarzon所指出的:

    • 没有 -RawGet-Content逐行输出目标文件的行,这些行(隐式)收集起来会形成一个由多行组成的数组 - 而不是单个的、多行的字符串,而-Raw则会返回这样的字符串。

      • 无论哪种方式,Get-Content都会将文件内容读入.NET字符串中,这些字符串由UTF-16代码单元([char]实例)组成,并且为了确保正确解释文件内容,您可能需要使用-Encoding参数。

      • [System.Text.Encoding]::Unicode.GetBytes()总是在内存中操作.NET字符串。

    • 当将一个数组传递给期望一个单一[string]参数的.NET方法时,PowerShell会自动通过空格连接其元素进行字符串化。

      • 因此,输入字符串中的换行符(换行)会丢失(被替换为空格),这可能会导致破损的代码,因为换行符在PowerShell代码中具有语法意义。

值得注意的是,文档告诉我们针对二进制文件使用 -Encoding byte 参数(在 v5.1 文档版本中)。 - Santiago Squarzon
1
@Santiago,问题的前提是将一个字符串编码为Base64,并且PowerShell要求这样的字符串必须是UTF-16LE编码的,以便与其-EncodedCommand CLI参数一起使用。如果您将输入字符串作为来自文件的字节流(在WinPS中为-Encoding Byte,在PS Core中为-AsByteStream)读取,并将收集到的字节数组直接传递给[System.Convert]::ToBase64String(),那么它只有在该文件恰好是UTF-16LE编码并且该文件没有BOM的情况下才能正常工作——这在UTF-16文件的情况下不太可能发生。 - mklement0
1
非常感谢您对这里正在发生的事情进行了全面的分解。虽然我能够做一些研究并得出结论,但直接导致问题的原因直到现在才被我理解。当然,使它工作是好的,但现在理解为什么它现在可以工作绝对是一件美妙的事情,我再次非常感激。 - I am Jakoby

4

我最终进行了更多的研究,找到了一种方法完全符合我的需求,并且保持了所有的完整性。

$encoded = [Convert]::ToBase64String(
  [System.Text.Encoding]::Unicode.GetBytes(
    (Get-Content -Path $Path -Raw -Encoding UTF8)
  )
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接