如何从PowerShell中的外部命令输出获取原始二进制数据? [英] How to get original binary data from external command output in PowerShell?
问题描述
我在这里已经读到,当您在Powershell中运行外部命令时,它们的输出始终被解释为字符串或字符串数组: https: //stackoverflow.com/a/35980675/983442
I have read here that when you run external commands in powershell, their output is always interpreted as a string or string array: https://stackoverflow.com/a/35980675/983442
我正在尝试处理外部命令的二进制输出,但是PowerShell似乎只能给我字符串.
I'm trying to process binary output from an external command, but it seems like PowerShell can only give me strings.
这让我想知道,什么编码用于将二进制数据转换为字符串?而且,它如何解释换行符以将二进制数据划分为字符串数组?它似乎只在\n
字符上分割,但我确定它也会在\r\n
上分割.
This leaves me wondering, what encoding is used to convert the binary data into strings? And also, how does it interpret newlines in order to divide the binary data into a string array? It seems to be splitting on the \n
character alone, but I'm sure it would also split on \r\n
.
有没有一种可靠的方法来获取powershell给我的字符串并将其转换为字节数组?
Is there even a reliable way to take the strings powershell gives me and turn them back into a byte array?
例如,假设我有一个包含以下内容的批处理文件,将其命名为thing.bat
:
For example, let's say I have a batch file with the following contents, call it thing.bat
:
@echo off
type image.jpg
然后运行以下Powershell:
I then run the following 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?
How can I reliably recreate this image.jpg in PowerShell once I have the $x
variable?
推荐答案
PowerShell假定,您调用的每个外部程序在其输出流上仅提供string
.
虽然这离现实还差得很远,但人们可能想从外部程序获取真实字节.
为此,我们将从头开始"创建一个新流程
PowerShell assumes, that every external program called by you provides only string
s over it's output stream.
While this is not so far from reality, one might want to get the real bytes from an external program.
To achieve that, we will create a new process "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()
哪个为我们提供了 StreamReader
用于StandardOutput
和StandardError
,当相应的重定向属性设置为$true
时.
Which provides us a StreamReader
for StandardOutput
and StandardError
, when the respective Redirect properties are set to $true
.
Now to get the stream's content we could easily use ReadToEnd()
like $outContent = $proc.StandardOutput.ReadToEnd()
, but that would give us just a string again.
A StreamReader
为我们提供了以下方法(以及其他方法):
A StreamReader
gives us the following methods (amongst others):
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()
Just create and pass a char[]
buffer to Read()
and use it like you want:
$length = $proc.StandardOutput.Length
$s = New-Object 'char[]' $length
$proc.StandardOutput.Read($s, 0, $length - 1)
第二个-更简单但不灵活的解决方案:
A second - easier but less flexible solution:
如果在将文件写入磁盘时没有问题,则可以使用-Encoding Oem
轻松地将程序的标准输出重定向到文件,然后使用Get-Content
重新读入:
If you don't have a problem writing files to disk you could easily redirect the program's standard output to a file with -Encoding Oem
and read it in again with Get-Content
:
& .\thing.bat | Out-File -FilePath "C:/tmp/out.txt" -Encoding Oem
$rawContent = Get-Content -Path "C:/tmp/out.txt" -Encoding Oem
这篇关于如何从PowerShell中的外部命令输出获取原始二进制数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!