如何从 PowerShell 中的外部命令输出中获取原始二进制数据?
How to get original binary data from external command output in PowerShell?
我在这里读到,当您在 powershell 中 运行 外部命令时,它们的输出总是被解释为字符串或字符串数组:
我正在尝试处理来自外部命令的二进制输出,但 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
s。
虽然这与现实相去不远,但您可能希望从外部程序中获取真正的字节。
为此,我们将创建一个新流程 "from scratch"
$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()
当相应的重定向属性设置为 $true
.
时,它为 StandardOutput
和 StandardError
提供了 StreamReader
现在要获取流的内容,我们可以像 $outContent = $proc.StandardOutput.ReadToEnd()
一样轻松地使用 ReadToEnd()
,但这只会再次给我们一个字符串。
A 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
:[=30= 再次读取它]
& .\thing.bat | Out-File -FilePath "C:/tmp/out.txt" -Encoding Oem
$rawContent = Get-Content -Path "C:/tmp/out.txt" -Encoding Oem
我在这里读到,当您在 powershell 中 运行 外部命令时,它们的输出总是被解释为字符串或字符串数组:
我正在尝试处理来自外部命令的二进制输出,但 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
s。
虽然这与现实相去不远,但您可能希望从外部程序中获取真正的字节。
为此,我们将创建一个新流程 "from scratch"
$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()
当相应的重定向属性设置为 $true
.
StandardOutput
和 StandardError
提供了 StreamReader
现在要获取流的内容,我们可以像 $outContent = $proc.StandardOutput.ReadToEnd()
一样轻松地使用 ReadToEnd()
,但这只会再次给我们一个字符串。
A 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
:[=30= 再次读取它]
& .\thing.bat | Out-File -FilePath "C:/tmp/out.txt" -Encoding Oem
$rawContent = Get-Content -Path "C:/tmp/out.txt" -Encoding Oem