これは何?
PowerShell の文字化けの原因は、基本的に以下の2つである。
- 出力される文字コードと期待される文字コードの不一致
- フォント指定の誤り、あるいは意図しないフォントへの強制変更
ここでは、これらの問題への基本的な対応案を整理する。
前提知識
前提となる知識は以下のとおり。
PowerShellのバージョンの違い
PowerShellには、.NET Framework がベースの WindowsPowerShell と、.NET がベースで マルチプラットフォームの PowerShell がある。現在のサポートOSであれば、WindowsPowerShell 5.1 はプリインストールされている。PowerShell 7.x は明示的にインストールする必要がある。
シェル部分
| Ver | プラットフォーム | フレームワーク | サポート期間 | 実行ファイル |
|---|---|---|---|---|
| 5.1 | Win | .NET Framework | OS依存 | powershell.exe |
| 7.x | Win,Mac,Linux | .NET | リリースから1.5~3年 | pwsh.exe |
ターミナルとの組み合わせ
| インターフェース(ターミナル) | 起動できるシェル | よくある利用シーン |
|---|---|---|
| コマンドプロンプト (黒い画面) | cmd.exe | 古いバッチファイルの実行 |
| PowerShellコンソール (青い画面) | powershell.exe | 標準のWindows管理 |
| Windows ターミナル (タブ形式の黒い画面) | pwsh.exe / cmd.exe / wsl | 現代の推奨環境。 複数同時並行。 |
関連する文字コード
- ASCII
- すべての文字コードの基礎となる 7bit の規格。英数字と一部の記号のみを扱い、日本語は含まれない。欧米のWindowsでは、このASCIIと互換性を持たせた8bitの「コードページ 1252 (ANSI)」や「コードページ 437 (OEM)」が標準的に使われる。
- Shift-JIS (CP932)
- 日本語 Windows の標準文字コード。厳密には、標準規格の Shift_JIS に Microsoft が独自拡張(NEC/IBM選定外字など)を加えた「Windows-31J (CP932)」を指す。Windows 11 のシステム設定で「ベータ版: Unicode UTF-8 を使用」を有効にしない限り、コンソールや古いアプリケーションのデフォルトとなる。
- UTF-16LE
- Unicode の 16bit 符号化方式。Windows OS の内部処理用コードとして採用されている。コードページは 1200。
- UTF-8
- Unicode の 8bit 符号化方式。英数字は ASCII と完全な互換性があり、世界標準として普及している。BOMなしが一般的。コードページは 65001。
文字コードに関わる設定
コンソール表示の文字コードとパイプでの文字コードが一致していないことが、多くの問題の原因であると考えられる。
| 項目 | [Console]::OutputEncoding |
$OutputEncoding |
|---|---|---|
| 定義場所 | .NET System.Console クラス | PowerShell 自動変数 (Preference) |
| 主な役割 | 画面(ディスプレイ)への表示規則 | 外部プロセス(exe)への送信規則 |
| 影響する時 | 外部コマンドの実行結果を画面で見るとき | 外部コマンドにパイプで文字を渡すとき |
| 5.1 デフォルト | システムロケール (通常 Shift-JIS) | ASCII |
| 7.x デフォルト | システムロケール (通常 Shift-JIS) | UTF-8 |
PowerShellでよく使われるツールのデフォルト出力
基本的に UTF-8 だが、wsl のヘルプが例外的に UTF-16LE となっているようだ。
| ツール | 出力のデフォルト | 備考 |
|---|---|---|
| winget | UTF-8 | |
| wsl | UTF-8(通常) | Linuxコマンドの多くはUTF-8で出力される。 |
| wsl --help | UTF-16LE | WSLバイナリ自体のヘルプ等はUTF-16LEで出力されるため注意。 |
方針・対応案
個人的に面倒が少ないと考える方針・対応案は次のとおり。
1. Windows PowerShell 5.1
- 現行サポートOSにはプリインストールされており、システムコンソールとして用いるので、使用感を共通化するため、プロファイルの変更は行わない
- 入出力において、必要な場合にエンコーディングを明示的に指定する
- 編集・実行環境の Windows PowerShell ISE があるので、スクリプトのエンコーディングは、UTF-16LE とする
2. PowerShell 7.x
- ユーザーが意図的にインストールしたはずなので、プロファイルで使いやすいように設定する。つまり、
$OutputEncodingの初期値が UTF-8 なので、[Console]::OutputEncodingを UTF-8 に揃える - WSLバイナリ(help等)の出力が UTF-16LE になる場合があるため、$env:WSL_UTF8 = 1 を設定して標準入出力を UTF-8 に強制する
- スクリプトのエンコーディングは、UTF-8 とする
- Winget, WSL, VScode で呼び出すシェルとしては、こちらを使う
設定方法
PowerShellからプロファイル設定をノートパッドで呼び出す。
notepad $profile
プロファイルに以下を追記する。これ以降、起動したコンソールで有効になる。
# 起動時のエンコーディングを記憶しておく(復元用)
$script:DefaultOutputEncoding = [Console]::OutputEncoding
$script:DefaultInputEncoding = [Console]::InputEncoding
$script:DefaultExternalEncoding = $OutputEncoding
# UTF-8に設定する関数
function Set-ConsoleUtf8 {
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$Global:OutputEncoding = [System.Text.Encoding]::UTF8
$env:WSL_UTF8 = 1
Write-Host "Encoding set to UTF-8 (CP65001)" -ForegroundColor Cyan
}
# 元の設定に戻す関数
function Restore-ConsoleEncoding {
[Console]::OutputEncoding = $script:DefaultOutputEncoding
[Console]::InputEncoding = $script:DefaultInputEncoding
$Global:OutputEncoding = $script:DefaultExternalEncoding
Remove-Item env:WSL_UTF8 -ErrorAction SilentlyContinue
Write-Host "Encoding restored to default ($($script:DefaultOutputEncoding.WebName))" -ForegroundColor Green
}
# デフォルトでUTF-8を有効化
Set-ConsoleUtf8
3. Windows ターミナルでのフォントの設定
Windowsターミナルの既定値のフォントは「Cascadia Mono」となっている。このフォントはコマンド ライン アプリケーションとテキスト エディターに新しいエクスペリエンスを提供する、Microsoft の新しいモノスペース フォントで、Windowsターミナルとともに開発された、とのことなので、問題なければそのまま使うのでよいと思う。フォントフォールバック機能により、日本語も表示できるようになっている。
Windows 11 で利用可能なフォントは以下で公開されている。「設定>追加の設定>外観>フォントフェイス」では、ここに含まれているものの他、インストールされているフォントの中から等幅等の条件でフィルタリングされ、プルダウンで設定可能なフォントとしてリストアップされるようだ。
コンソールで日本語と思しき箇所が豆腐(白い四角)で表示される場合は、このフォント設定を確認する。「MS ゴシック」や「BIZ UDゴシック」に変更することで、文字化けが解消する可能性がある。
出典・参考
PowerShell プロファイルは、PowerShell の起動時に実行されるスクリプトです。 プロファイルをスタートアップ スクリプトとして使用して、環境をカスタマイズできます。
コンソールが出力の書き込みに使用するエンコードを取得または設定します。
データをネイティブ アプリケーションにパイプするときに PowerShell で使用される文字エンコード方法を決定します。
UTF8エンコーディングを使用するためのオプトイン環境変数を追加する
- WSL_UTF8=1 CRT を介して標準出力と標準エラー出力に UTF8 エンコーディングを強制するためのオプトイン環境変数を追加します。
Windows は UTF-16 (WCHAR) でネイティブに動作するので、場合によっては、Windows API と相互運用するために UTF-8 データを UTF-16 (またはその逆) に変換する必要があります。
Cascadia Code は、コマンド ライン アプリケーションとテキスト エディターに新しいエクスペリエンスを提供する、Microsoft の新しいモノスペース フォントです。 Microsoft では、Windows ターミナルと共に Cascadia Code を開発しました。
本事象は Windows Server 2022 ならびに Windows 11 における Windows PowerShell の既定のフォントが “Consolas” に設定されていることによって発生いたします。”Consolas” には CJK 文字を表示するためのグリフが含まれていないため、日本語、中国語を表示することができず、文字を正しく表示することができません。
*Windows PowerShell のフォントに “MS ゴシック” が設定されている場合、本事象は発生いたしません。