WindowsシステムロケールがUTF-8コードページを使用しているかどうかを検出するスクリプト?

Nov 21 2020

Win10の最近のバージョンでは、アクティブコードページ(ACP)をUTF-8コードページに設定することができます。また、ここで説明するように、UTF-8コードページを使用するようにシステムロケール(Windows APIの「A」バージョンと「W」バージョンの間のマッピングに使用)を設定することができます。

スクリプトは、UTF-8コードページが使用されているかどうかをどのように検出しますか?

こことここで説明したように、通常はWMIを使用してシステムコードページIDを取得できます。

For Each os In wmi.ExecQuery("SELECT * FROM Win32_OperatingSystem")
    cs = os.CodeSet
Next

非ユニコードプログラムに対してアメリカ英語で「ベータ」utf-8サポートを使用するように設定されたWin10でそれを試してみると、WMIはコードページが1252であると報告し続けます。コードポイントは128ですが、49800にはありません:UTF-8のコードポイントは49800にあり、128にはありません)。

スクリプトは、実際のシステムロケールがUTF-8コードページを使用していることをどのように検出しますか?

回答

4 mklement0 Nov 21 2020 at 12:19

PowerShell(シェルベース)ソリューション:

決定するためのシステムロケールの(システム全体)OEMコードページ-で使用されるものであり、コンソールアプリケーション、レジストリを使用します。

# $true, if the OEM code page is set to UTF-8 (code page 65001)
'65001' -eq (Get-ItemPropertyValue HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage OEMCP)

注意:

  • 使用してシステム全体のUTF-8をサポートも(ANSIコードページを設定ACP)する65001ことにより、使用、従来のGUIアプリケーションが、特にもWindows PowerShellの[1]のWindows PowerShellの既定のためにエンコードすることを意味し、Get-ContentそしてSet-Content例えば、コマンドレットは変化します。

  • からcmd.exe、を実行できますが
    reg.exe query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v OEMCP、そのテキスト出力を解析して、コードページ番号のみを抽出する必要があります。

  • 残念ながら、PowerShellのGet-WinSystemLocaleコマンドレットは、この記事の執筆時点では使用できません。[cultureinfo]返されるインスタンスは、配置されている可能性のあるUTF-8オーバーライドを反映していないためです。このServerFaultの回答を参照してください。


現在のコンソールのアクティブなOEMコードページを判別するには-コンソールウィンドウはカスタムコードページを使用するように構成でき、コードページはセッション中に事前に変更されている可能性があるため、システムロケールを反映している場合と反映していない場合があります。

# $true, if the OEM code page is set to UTF-8 (code page 65001)
65001 -eq [Console]::OutputEncoding.CodePage

注意:

  • からcmd.exe実行することもできchcp chcp.comますが、そのテキスト出力を解析して、コードページ番号だけを抽出する必要があります。

Windows APIベースのソリューション

コンパイルされたアプリケーションから、GetACP()およびGetOEMCP() Windows API関数を使用して、アクティブなANSIおよびOEMコードページをそれぞれクエリできます。

PowerShellからそれを行うこともできます(ただし、オンデマンドコンパイルが必要であるため、レジストリソリューションが最上位にあることが望ましいです)。

# Compile a helper type that calls the WinAPI functions.
Add-Type -Namespace Util -Name WinApi -MemberDefinition @'
  [DllImport("Kernel32.dll")]
  public static extern uint GetACP();
  [DllImport("Kernel32.dll")]
  public static extern uint GetOEMCP();
'@

[Util.WinAPI]::GetOEMCP(), [Util.WinAPI]::GetACP()

注意:

  • コンパイルされたアプリケーションがコンソールアプリケーションであり、関連するコンソールの現在のOEMコードページ(システムロケールを介して設定されたデフォルトページである場合とそうでない場合があります)を知りたい場合は、GetConsoleOutputCP()代わりに関数を使用してください。

[1]アクティブなANSIコードページはPowerShell [Core] v6 +とは関係がなくなり、コマンドレットにBOMのないUTF-8を一貫して使用しますが、Windowsでは、に反映されているように[Console]::OutputEncoding、アクティブなOEMコードページは通信時に引き続き重要です。外部プログラム