1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PowerShellでバイナリ(もしくはエンコーディングが不明なデータ)を扱う

Posted at

パイプラインとリダイレクト

PowerShellでは、普通のシェルと同じ方法でリダイレクトやパイプラインを行った場合、ストリームの内容が文字列に変換されて扱われるという特徴があります。
データによってはエンコーディングの変換でデータが欠落し、通常のコマンドプロンプトと異なる動作になります。

欠落例

これらはエンコーディングの変換によってデータが欠落します。

# 欠落例1
.\bin.exe > bin_fail1.bin

# 欠落例2
$bin_fail = .\bin.exe

成功例

次の方法ではエンコーディングの変換なしにデータを取得できます。

# コマンドラインインタプリタで標準出力を処理する
cmd /c "bin.exe > bin_cmd.bin"

# バイナリを読み出す
[byte[]]$bin_gc = Get-Content -Path .\bin_cmd.bin -Encoding Byte

# バイナリを書き出す
Set-Content -Path "out_sc.bin" -Value $bin_gc -Encoding Byte

おまけ

コマンドラインインタプリタを使わずパイプでバイナリを得ます。

invoke.ps1
# コマンド実行時の標準出力をByte Arrayで得る
function Invoke-BinaryPipe {
    Param($FileName, $Arguments)
    if (-not $FileName) {
        Write-Host "Usage Invoke-BinaryPipe <FileName>"
        return
    }
    [System.Diagnostics.ProcessStartInfo]$psi = New-Object -TypeName System.Diagnostics.ProcessStartInfo
    $ExecPath = (Convert-Path $FileName)
    $psi.WorkingDirectory = (Get-Location).Path
    $psi.RedirectStandardOutput = $true
    $psi.UseShellExecute = $false
    $psi.FileName = $ExecPath
    $psi.Arguments = $Arguments
    [System.Diagnostics.Process]$proc = [System.Diagnostics.Process]::Start($psi)
    if (-not $proc) { return }

    $proc.WaitForExit()
    [System.IO.MemoryStream]$ms = New-Object System.IO.MemoryStream
    $proc.StandardOutput.BaseStream.CopyTo($ms)
    $ms.ToArray()
    $proc.Dispose()
}

[byte[]]$bin = Invoke-BinaryPipe "./bin.exe"

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?