2バイト目に ASCII コードがくることを想定していないコンソールアプリなど、標準出力を UTF-8 として使用するコンソールアプリは少なくない。
しかし、PowerShell は標準では UTF-8 の標準出力をそのまま読み取ることができない。
(後述するが、単純な方法はある)
そういった場合でも、.NET Framework を駆使すれば、ちゃんと文字列として取得できる。
たとえば、以下のようなバッチファイルを、 utf8out.bat などとして用意しておく。
(ちゃんと標準ストリームを使用していることを明確にするため、あえてバッチで書いた)
@echo off
powershell -Nologo -Command "$binutf8 = [Text.Encoding]::UTF8.GetBytes([char[]]@('(','(',0x3044,0x308D,0x306F,0x306B,')',')')); [Console]::OpenStandardOutput().Write($binutf8, 0, $binutf8.Count);"
これをそのまま実行すると、
((縺・m縺ッ縺ォ))
などと文字化けしてしまうことだろう。
これを、 System.Diagnostics.Process クラスを使って、標準出力をリダイレクトさせ、それを UTF-8 エンコードで取り込ませる。
$psi = New-Object Diagnostics.ProcessStartInfo
$psi.FileName = "utf8out.bat"
$psi.UseShellExecute = $false # プロセス起動時にシェルを使わず、標準出力をリダイレクト可能にする
$psi.StandardOutputEncoding = [Text.Encoding]::UTF8 # 文字コードを指定
$psi.RedirectStandardOutput = $true
$p = [Diagnostics.Process]::Start($psi)
$s = $p.StandardOutput.ReadToEnd()
$s
$p.WaitForExit()
そうすれば、出力は以下のように文字化けせずに表示されるはずだ。
((いろはに))
これで、UTF-8 を使うアプリとの連携もばっちりだ。
ちなみに、 FileName プロパティで指定するファイルの相対パスは、 PowerShell の カレントディレクトリではなく、 .NET のカレントディレクトリ ([System.IO.Directory]::GetCurrentDirectory()
/ [System.IO.Directory]::SetCurrentDirectory(...)
で取得/設定できる物) である点に注意。
PowerShell v3 以上であれば、以下のように もうちょっときれいに書くこともできる。
#Requires -Version 3
$p = [System.Diagnostics.Process]::Start(
[System.Diagnostics.ProcessStartInfo]@{
FileName = 'utf8out.bat';
UseShellExecute = $false;
StandardOutputEncoding = [Text.Encoding]::UTF8;
RedirectStandardOutput = $true;
}
);
$p.WaitForExit();
$s = $p.StandardOutput.ReadToEnd();
$p.Dispose();
$s;
…と、ここまでは 2011年頃が初稿の記事だったのだが、 2023年現在利用可能な Windows PowerShell 5.1 や PowerShell 7.2 の場合、以下のように [System.Console]::OutputEncoding
に適切な文字コードを設定してやれば、キチンと受け取れる。
[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8;
.\utf8out.bat | Tee-Object -Variable rett;
ちなみに、外部コマンドの標準出力を PowerShell で受け取る場合は [System.Console]::OutputEncoding
プロパティに、 PowerShell の出力を外部コマンドの標準入力に渡す場合は $OutputEncoding
自動変数に、それぞれ適切な文字コードを設定する必要がある。
それぞれの初期値は以下の通り。
\ | Windows PowerShell 5.1以下 | PowerShell 6以上 |
---|---|---|
[System.Console]::OutputEncoding プロパティ |
システムロケールの文字コード | 〃 |
$OutputEncoding 自動変数 |
US-ASCII | BOM 無し UTF-8 |