Micha Wiedenmann
Micha Wiedenmann

Reputation: 20823

How to pipe the output of a command to a file without powershell changing the encoding?

I want to pipe the output of a command to a file:

PS C:\Temp> create-png > binary.png

I noticed that Powershell changes the encoding and that I can manually give an encoding:

PS C:\Temp> create-png | Out-File "binary.png" -Encoding OEM

However there is no RAW encoding option, even the OEM option changes newline bytes (0xA resp 0xD) to the windows newline byte sequence (0xD 0xA) thereby ruining any binary format.

How can I prevent Powershell from changing the encoding when piping to a file?

Related questions

Upvotes: 4

Views: 2898

Answers (4)

傅继晗
傅继晗

Reputation: 1137


Powershell regard output as string.But windows-1252 maps every byte to character,you can try use this encoding.
It's a trick though it is not efficient.
In my case,powershell version is 5.1,Out-File or > operator doesn't support windows 1252,so I have to use WriteAllText method. example:

[console]::outputencoding=[console]::inputencoding=[System.Text.Encoding]::GetEncoding(1252)
$result=python zipbomb --mode=quoted_overlap --num-files=250 --compressed-size=21179
[IO.File]::WriteAllText("$pwd\result.zip",$result,[System.Text.Encoding]::GetEncoding(1252))

or simply by Start-Process with -RedirectStandardOutput option

Start-Process -FilePath "python.exe" -ArgumentList "zipbomb --mode=quoted_overlap --num-files=250 --compressed-size=21179" -RedirectStandardOutput output.zip

Upvotes: 1

Hardy
Hardy

Reputation: 51

Create a batchfile containing the line

create-png > binary.png

and call that from Powershell via

& cmd /c batchfile.bat

If you'd rather pass the command to cmd as command line parameter:

$x = "create-png > binary.png"
& cmd /c $x

Upvotes: 2

RickH
RickH

Reputation: 2486

Try using set-content:

create-png | set-content -path myfile.png -encoding byte

If you need additional info on set-content just run

get-help set-content

You can also use 'sc' as a shortcut for set-content.

Tested with the following, produces a readable PNG:

function create-png()
{
    [System.Drawing.Bitmap] $bitmap = new-object 'System.Drawing.Bitmap'([Int32]32,[Int32]32);
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap);
    $graphics.DrawString("TEST",[System.Drawing.SystemFonts]::DefaultFont,[System.Drawing.SystemBrushes]::ActiveCaption,0,0);
    $converter = new-object 'System.Drawing.ImageConverter';
    return([byte[]]($converter.ConvertTo($bitmap, [byte[]])));
}

create-png | set-content -Path 'fromsc.png' -Encoding Byte

If you are calling out to a non-PowerShell executable like ipconfig and you just want to capture the bytes from Standard Output, try Start-Process:

Start-Process -NoNewWindow -FilePath 'ipconfig' -RedirectStandardOutput 'output.dat'

Upvotes: 5

Micha Wiedenmann
Micha Wiedenmann

Reputation: 20823

According to this well written blog article

When using curl with PowerShell, never, never redirect to file with >. Always use the –o or –out switch. If you need to stream the output of curl to another utility (say gpg) then you need to sub-shell into cmd for the binary streaming or use temporary files.

Upvotes: 1

Related Questions