1. ホーム
  2. windows

[解決済み] コマンドプロンプト / Windows PowershellでUTF-8エンコーディング(CHCP 65001)を使用する(Windows 10)

2022-03-04 15:02:11

質問

を無理矢理使っているのですが chcp 65001 が、SOや他のコミュニティーのQ&Aの投稿から判断すると、それは 危険で非効率的なソリューションのように思われる . マイクロソフトは、以下のような改良された/完全な代替手段を提供していますか? chcp 65001 レジストリを手動で変更することなく、永久に保存することができるのでしょうか?また、そうでない場合、将来的にWindows CLIでUTF-8をサポートするためのスケジュールやアジェンダが公に発表されているのでしょうか?

個人的には chcp 949 は韓国語文字サポート用ですが、バックスラッシュの表示が変なので \ という文字や、いくつかのアプリケーション(Neovimなど)で不正確な表示や理解不能な表示をすることがあります。 ではありません。 韓国語は 949 は最近問題になっているようです。

解決方法は?

注意

  • この回答では 文字 エンコーディング をWindowsコンソールで
    UTF-8 (コードページ 65001 というように 貝殻 など cmd.exe とPowerShellをきちんと エンコードとデコード との通信では、文字(テキスト)を 外部(コンソール)プログラム ユニコード完全対応 で、そして cmd.exe は、ファイルI/Oにも対応しています。 [1]

  • 対照的に、あなたの関心が、制限という個別の側面に関するものであるなら ユニコード文字 レンダリング の中段と下段をコンソールウィンドウで見てください。 この回答 コンソール(端末)アプリケーションの代替品についても説明しています。


マイクロソフトは、レジストリを手動で変更せずに永久に保存できる、chcp 65001の改良型/完全な代替品を提供していますか?

現在(少なくとも) Windows 10 バージョン1903では、以下のオプションがあります。 を設定します。 システムロケール ( 非Unicodeプログラム用言語 ) をUTF-8に変換する。 が、しかし 機能は まだベータ版 この記事を書いている時点では .

起動するには

  • 実行する intl.cpl (コントロールパネルの地域設定を開きます)
  • 以下のスクリーンショットの指示に従ってください。

  • これは セット 両方 システムのアクティブなOEM および へのANSIコードページ 65001 UTF-8コードページ であるため、(a) 今後すべての コンソールウィンドウ を使用する OEM コードページのデフォルトはUTF-8です(まるで chcp 65001 が実行されていました。 cmd.exe ウィンドウ)、(b)はレガシーな非ユニコードである GUI -サブシステムのアプリケーションで、(中略) ANSI コードページでは、UTF-8を使用します。

    • 注意事項 :

      • を使用している場合 Windows PowerShell を作成します。 Get-ContentSet-Content そして、Windows PowerShell がデフォルトでシステムのアクティブな ANSI コードページを使用するその他のコンテキスト、特に 読み ソースコード BOMレスファイルから , デフォルトはUTF-8 (これはPowerShellの コア (v6+)では常にそうなっています)。これはつまり -Encoding 引数を使用すると、ANSIエンコードされたBOMなしファイル(これは歴史的によくあることです)は誤読され、また Set-Content はANSI-encodeではなくUTF-8になります。

      • [ PowerShell 7.1 で修正されました。 ] 少なくとも PowerShell 7.0 までは。 a バグ を使用すると、PowerShell で次のようなバグが発生します。 : UTF-8 BOM の設定に関係なく、標準入力経由で外部プロセスに送信されるデータの先頭に予期せぬエラーが発生します。 $OutputEncoding に)、その中でも特に ブレーク Start-Job - 見る このGitHubの課題 .

      • すべてのフォントがUnicodeに対応しているわけではないので、TT(TrueType)フォントを選びますが、TTフォントでも通常は サブセット 全文字の そのため、気になる文字がすべて表現されているかどうかを確認するには、特定のフォントで実験する必要があるかもしれません。 この回答 また、より優れたUnicodeレンダリングサポートを持つ代替コンソール(ターミナル)アプリケーションについても説明しています。

      • として エリクサン が指摘する。 UTF-8を使用しないレガシーコンソールアプリケーションは、以下のように制限されます。 ASCIIのみの入力 を生成し 不正な出力 (7ビット)ASCIIの範囲外の文字を出力しようとしたとき . (時代遅れのWindows 7以下では、プログラムはさらに クラッシュ ).
        レガシーなコンソールアプリケーションの実行が重要な場合は、コメントにあるeryksunの推奨事項を参照してください。

  • しかし に対して Windows PowerShell ということです。 ではない 充分 :

    • さらに を設定します。 $OutputEncoding 環境変数に UTF-8 を設定します。 も同様に $OutputEncoding = [System.Text.UTF8Encoding]::new() [2] このコマンドを $PROFILE (現在のユーザーのみ) または $PROFILE.AllUsersCurrentHost (すべてのユーザー) ファイルを作成します。
    • 幸いなことに、PowerShellではこのようなことはもう必要ありません。 コア は、内部的に一貫してBOM-less UTF-8をデフォルトとしています。

を設定すると システムロケール をUTF-8にすることは ない を使用してください。 スタートアップコマンド の代わりに

注:上記のレガシーコンソールアプリケーションに関する注意点は、ここでも同様に適用されます。もし、レガシーなコンソールアプリケーションを実行することが重要であれば、コメントにあるeryksunの推奨事項を参照してください。

  • PowerShellの場合 (両方のエディション)に、次の行を追加してください。 $PROFILE (現在のユーザーのみ) または $PROFILE.AllUsersCurrentHost (すべてのユーザー) ファイルに相当します。 chcp 65001 を設定し、プリファレンス変数 $OutputEncoding を使用して、パイプライン経由で外部プログラムにデータを送信する際に、PowerShellにUTF-8で送信するように指示します。

    • を実行することに注意してください。 chcp 65001 から 内部 PowerShell セッションは ではない .NETは起動時にコンソールの出力エンコーディングをキャッシュし、後で chcp ;さらに、記載されているように Windows PowerShell が必要です。 $OutputEncoding が設定されていること - 参照 この回答 をご覧ください。
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding

  • たとえば、次のような行を、手っ取り早く $PROFILE をプログラムで作成します。
'$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding' + [Environment]::Newline + (Get-Content -Raw $PROFILE -ErrorAction SilentlyContinue) | Set-Content -Encoding utf8 $PROFILE

  • について cmd.exe で、レジストリを介して自動実行コマンドを定義します。 AutoRun キーの HKEY_CURRENT_USER\Software\Microsoft\Command Processor (現在のユーザーのみ)または HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor (すべてのユーザー)。

    • 例えば、PowerShellを使用してこの値を作成することができます。
# Auto-execute `chcp 65001` whenever the current user opens a `cmd.exe` console
# window (including when running a batch file):
Set-ItemProperty 'HKCU:\Software\Microsoft\Command Processor' AutoRun 'chcp 65001 >NUL'


オプションでお読みいただけます。なぜWindows PowerShellなのか ISE は、あまり良い選択ではありません。

ISE はより良い Unicode を備えていますが レンダリング はコンソールよりもサポートが充実していますが、一般的にはあまり良い選択とは言えません。

  • 何よりもまず ISEは 陳腐化 : PowerShell をサポートしていません。 コア また、PowerShell の両エディションに対応した新しいプレミア IDE とは異なり、クロスプラットフォームではありません。 ビジュアルスタジオコード PowerShell ではすでにデフォルトで UTF-8 が使用されています。 コア Windows PowerShellでもそのように設定することができます。

  • ISEは一般に、以下のような環境です。 開発中 スクリプトのためのものではありません。 実行する で実行されることを想定しておく必要があります (他の人のためにスクリプトを (も) 書いている場合は コンソール ); 特筆すべきは に対して ランニング のコードでは、ISEの動作は、通常のコンソールの動作とは異なります :

    • 動作のサポートが悪い 外部プログラム をサポートしていないことだけが原因ではありません。 インタラクティブ のもの(次を参照)だけでなく 文字エンコーディング ISEは外部プログラムが ANSI コードページがデフォルトで使用されますが、実際には OEM コードページがあります。例えば、デフォルトでは、この単純なコマンドは、単に cmd.exe を通すと誤動作します(修正方法は以下を参照)。
      cmd /c echo hü | Write-Output

    • ドットソーシング スクリプトファイルの呼び出しを 子スコープ (後者は通常のコンソールウィンドウで起こること)、すなわち 繰り返し で実行されます。 全く同じスコープ . このため、前の実行で残した定義が後の実行に影響を与えるという微妙なバグが発生することがあります。

  • として エリクサン が指摘する。 ISEは インタラクティブ 外部コンソールプログラム つまり、ユーザーの入力を必要とするものです。

問題は、コンソールを隠して、プロセスの出力(入力ではなく)をパイプにリダイレクトしてしまうことです。ほとんどのコンソールアプリケーションは、ファイルがパイプになるとフルバッファリングに切り替わります。また、インタラクティブなアプリケーションではstdinからの読み込みが必要ですが、これは隠されたコンソールウィンドウからは不可能です。(非表示にするには ShowWindow しかし、入力用の別ウィンドウは不格好です)。

  • この制限に耐えられるのであれば、アクティブなコードページを 65001 (UTF-8)で外部プログラムと正しく通信するためには、厄介な回避策が必要です。

    • を実行して、隠しコンソールウィンドウを強制的に作成する必要があります。 任意の 外部プログラムを内蔵コンソールから、例えば chcp - をクリックすると、コンソールウィンドウが一瞬点滅するのが見えます。

    • のみ では を設定することができます。 [console]::OutputEncoding (そして $OutputEncoding をUTF-8に変換します(隠しコンソールがまだ作成されていない場合は、上記のように handle is invalid error ).


[1] PowerShellでは、もし一度も 外部 プログラムであれば、システムロケール(アクティブコードページ)を気にする必要はありません。PowerShell ネイティブコマンドと .NET 呼び出しは、常に UTF-16 文字列(ネイティブ .NET 文字列)で通信し、ファイル I/O では、システムロケールに依存しないデフォルトエンコーディングが適用されます。同様に ユニコード Windows API 関数のバージョンは、コンソールへの印刷とコンソールからの読み取りに使用され、非 ASCII 文字は常に (コンソールのレンダリング制限内で) 正しく印刷されます。
cmd.exe これとは対照的に、システムロケールはファイルI/Oに重要です( <> リダイレクト、特にバッチファイルのソースコードにどのようなエンコーディングを仮定するかなど)、メモリ上の外部プログラムと通信するためだけでなく(例えば、プログラム出力を for /f ループ)。

[2] PowerShell v4-では、静的な ::new() メソッドが利用できない場合は $OutputEncoding = (New-Object System.Text.UTF8Encoding).psobject.BaseObject . 参照 GitHub issue #5763 というのは、なぜ .psobject.BaseObject の部分が必要です。