用于检测 Windows 系统区域设置是否使用 UTF-8 代码页的脚本?

dav*_*vid 1 vbscript powershell wmi utf-8 windows-10

在最新版本的 Win10 上,可以将活动代码页 (ACP) 设置为 UTF-8 代码页。正如此处所讨论的,可以将系统区域设置(用于在 Windows API 的“A”版本和“W”版本之间进行映射)设置为使用 UTF-8 代码页。

脚本如何检测 UTF-8 代码页是否正在使用?

正如此处此处所讨论的,通常可以使用 WMI 来获取系统代码页 ID:

For Each os In wmi.ExecQuery("SELECT * FROM Win32_OperatingSystem")
    cs = os.CodeSet
Next
Run Code Online (Sandbox Code Playgroud)

当我在 Win10 上尝试该操作时,设置对非 unicode 程序使用美式英语的“beta”utf-8 支持,WMI 继续报告代码页为 1252。尽管情况显然并非如此(代码页 1252 有128 处有一个代码点,但 49800 处没有代码点:UTF-8 49800 处有一个代码点,128 处没有代码点)。

脚本如何检测实际系统区域设置是否使用 UTF-8 代码页?

mkl*_*nt0 5

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)
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 使用系统范围的 UTF-8 支持还会将 ANSI 代码页 ( ACP) 设置为,由旧版 GUI 应用程序65001使用,但值得注意的是Windows PowerShell [1] ,这意味着 Windows PowerShell和cmdlet的默认编码会发生变化。Get-ContentSet-Content

  • cmd.exe,您可以运行
    reg.exe query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage /v OEMCP,但随后您必须解析其文本输出以仅提取代码页号。

  • 请注意,遗憾的是,Get-WinSystemLocale在撰写本文时,PowerShell 的 cmdlet 无法使用,因为[cultureinfo]它返回的实例未反映可能存在的 UTF-8 覆盖 - 请参阅此 ServerFault 答案


要确定当前控制台的活动 OEM 代码页- 这可能反映也可能不反映系统区域设置,因为控制台窗口可以配置为使用自定义代码页,并且代码页甚至可能事先在会话中更改:

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

笔记:

  • 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()
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 如果您编译的应用程序是控制台应用程序,并且您想知道关联控制台的当前 OEM 代码页(可能是也可能不是通过系统区域设置设置的默认页面),请改用该GetConsoleOutputCP()函数。

[1] 活动 ANSI 代码页不再与PowerShell [Core] v6+相关,PowerShell [Core] v6+ 始终在其 cmdlet 中使用无 BOM UTF-8,但在 Windows 上,活动 OEM 代码页(如 中所反映)[Console]::OutputEncoding在与外部程序