Skrypt do wykrycia, czy ustawienia regionalne systemu Windows używają strony kodowej UTF-8?

Nov 21 2020

W najnowszych wersjach Win10 możliwe jest ustawienie aktywnej strony kodowej (ACP) na stronę kodową UTF-8. Jak omówiono tutaj , możliwe jest ustawienie ustawień regionalnych systemu (używanych do mapowania między wersją „A” a wersją „W” interfejsu API systemu Windows) w celu korzystania ze strony kodowej UTF-8.

W jaki sposób skrypt wykrywa, czy używana jest strona kodowa UTF-8?

Jak omówiono tutaj i tutaj , zwykle można użyć WMI do uzyskania identyfikatora strony kodowej systemu:

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

Kiedy próbuję tego na Win10, ustawionym na obsługę utf-8 „beta” w amerykańskim języku angielskim dla programów innych niż Unicode, WMI nadal zgłasza, że ​​strona kodowa to 1252. Nawet jeśli wyraźnie tak nie jest (strona kodowa 1252 ma punkt kodowy 128, ale brak 49800: UTF-8 ma punkt kodowy 49800, brak 128).

W jaki sposób skrypt wykrywa, że ​​aktualne ustawienia regionalne używają strony kodowej UTF-8?

Odpowiedzi

4 mklement0 Nov 21 2020 at 12:19

Rozwiązania PowerShell (oparte na powłoce):

Aby określić ustawienia narodowe systemu (ogólnosystemowe) strony kodowej OEM - używanej przez aplikacje konsolowe , użyj rejestru:

# $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)

Uwaga:

  • Użycie ogólnosystemowej obsługi UTF-8 powoduje również ustawienie strony kodowej ANSI ( ACP) na 65001, używanej przez starsze aplikacje GUI, ale w szczególności także przez Windows PowerShell [1] , oznacza, że ​​domyślne kodowanie programu Windows PowerShell dla , na przykład, poleceń cmdlet Get-Contenti Set-Contentulegnie zmianie.

  • cmd.exeMożna by uruchomić program From ,
    reg.exe query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v OEMCPale wtedy musiałbyś przeanalizować jego tekstowe dane wyjściowe, aby wyodrębnić tylko numer strony kodowej.

  • Zauważ, że niestety Get-WinSystemLocalecmdlet PowerShell nie może być używany w chwili pisania tego tekstu, ponieważ [cultureinfo]zwracana instancja nie odzwierciedla zastąpienia UTF-8, które może być na miejscu - zobacz tę odpowiedź ServerFault .


Aby określić aktywną stronę kodową OEM bieżącej konsoli - która może, ale nie musi, odzwierciedlać ustawienia regionalne systemu, ponieważ okna konsoli można skonfigurować do używania niestandardowych stron kodowych, a strona kodowa mogła nawet zostać wcześniej zmieniona w sesji:

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

Uwaga:

  • Z cmd.exemożna wykonać chcp chcp.com, ale musiałbyś wtedy przeanalizować jego tekstowe wyjście, aby wyodrębnić tylko numer strony kodowej

Rozwiązanie oparte na Windows API :

Ze skompilowanej aplikacji można użyć funkcji GetACP () i GetOEMCP () Windows API do odpytywania odpowiednio aktywnej strony kodowej ANSI i OEM.

Możesz to nawet zrobić z PowerShell (chociaż fakt, że wymaga kompilacji na żądanie, sprawia, że ​​preferowane jest rozwiązanie rejestru na górze):

# 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()

Uwaga:

  • Jeśli Twoja skompilowana aplikacja jest aplikacją konsolową i chcesz poznać aktualną stronę kodową OEM skojarzonej konsoli - która może, ale nie musi być domyślną stroną ustawioną przez ustawienia regionalne systemu - użyj GetConsoleOutputCP()zamiast niej tej funkcji.

[1] Aktywna strona kodowa ANSI nie ma już znaczenia dla programu PowerShell [Core] v6 + , który konsekwentnie używa UTF-8 bez BOM w swoich poleceniach cmdlet, ale w systemie Windows aktywna strona kodowa OEM, jak widać w [Console]::OutputEncoding, nadal ma znaczenie podczas komunikacji z programy zewnętrzne .