繁体   English   中英

如何从 PowerShell 的外部命令输出中获取原始二进制数据?

[英]How to get original binary data from external command output in PowerShell?

我在这里读到,当你在 powershell 中运行外部命令时,它们的输出总是被解释为字符串或字符串数​​组: https : //stackoverflow.com/a/35980675/983442

我正在尝试处理来自外部命令的二进制输出,但似乎 PowerShell 只能给我字符串。

这让我想知道,使用什么编码将二进制数据转换为字符串? 而且,它如何解释换行符以将二进制数据划分为字符串数组? 它似乎仅在\\n字符上拆分,但我确定它也会在\\r\\n上拆分。

甚至有一种可靠的方法来获取powershell给我的字符串并将它们转换回字节数组吗?

例如,假设我有一个包含以下内容的批处理文件,将其thing.bat

@echo off
type image.jpg

然后我运行以下powershell:

PS> $x = & .\thing.bat
PS> $x.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS> $x[0].gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS> $x.count
36

有了$x变量后,如何在 PowerShell 中可靠地重新创建此 image.jpg?

PowerShell 假设,您调用的每个外部程序仅在其输出流上提供string 虽然这与现实相去甚远,但人们可能希望从外部程序中获取实际字节。 为了实现这一目标,我们将“从头开始”创建一个新流程

$procInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{
    FileName = "cmd.exe"
    Arguments = "thing.bat"
    RedirectStandardError = $true
    RedirectStandardOutput = $true
    UseShellExecute = $false
}
$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $procInfo
$proc.Start() | Out-Null
$proc.WaitForExit()

当相应的 Redirect 属性设置为$true时,它为我们提供了StandardOutputStandardErrorStreamReader

现在要获取流的内容,我们可以轻松地使用ReadToEnd()$outContent = $proc.StandardOutput.ReadToEnd() ,但这将再次给我们一个字符串。

StreamReader为我们提供了以下方法(其中包括):

Read             Method   int Read(), int Read(char[] buffer, int index, int count)
ReadAsync        Method   System.Threading.Tasks.Task[int] ReadAsync(char[] buffer, int index, int count)
ReadBlock        Method   int ReadBlock(char[] buffer, int index, int count)
ReadBlockAsync   Method   System.Threading.Tasks.Task[int] ReadBlockAsync(char[] buffer, int index, int count)
ReadLine         Method   string ReadLine()
ReadLineAsync    Method   System.Threading.Tasks.Task[string] ReadLineAsync()
ReadToEnd        Method   string ReadToEnd()
ReadToEndAsync   Method   System.Threading.Tasks.Task[string] ReadToEndAsync()

只需创建一个char[]缓冲区并将其传递给Read()并按照需要使用它:

$length = $proc.StandardOutput.Length
$s = New-Object 'char[]' $length
$proc.StandardOutput.Read($s, 0, $length - 1)

第二个 - 更简单但不太灵活的解决方案:

如果将文件写入磁盘没有问题,您可以轻松地将程序的标准输出重定向到带有-Encoding Oem的文件,然后使用Get-Content再次读取它:

& .\thing.bat | Out-File -FilePath "C:/tmp/out.txt" -Encoding Oem
$rawContent = Get-Content -Path "C:/tmp/out.txt" -Encoding Oem

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM