Skrypt do wykrycia, czy ustawienia regionalne systemu Windows używają strony kodowej UTF-8?
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
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
) na65001
, 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ń cmdletGet-Content
iSet-Content
ulegnie zmianie.cmd.exe
Można by uruchomić program From ,
reg.exe query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v OEMCP
ale 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.exe
moż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 .