如何从PowerShell中的外部命令输出获取原始二进制数据? [英] How to get original binary data from external command output in PowerShell?

查看:108
本文介绍了如何从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 strings 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 用于StandardOutputStandardError,当相应的重定向属性设置为$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()

只需创建一个char[]缓冲区并将其传递给

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆