首页 > 解决方案 > 检测 Windows 系统区域设置是否使用 UTF-8 代码页的脚本?

问题描述

在最新版本的 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

当我在 Win10 上尝试时,设置为在非 unicode 程序中使用美式英语中的“beta”utf-8 支持,WMI 继续报告代码页是 1252。即使情况显然不是这样(代码页 1252 有128 处的代码点,但 49800 处没有代码点:UTF-8 在 49800 处有代码点,128 处没有代码点)。

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

标签: powershellutf-8vbscriptwindows-10wmi

解决方案


PowerShell(基于 shell)解决方案:

要确定系统区域设置的(系统范围的)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-ContentSet-Contentcmdlet 的默认编码,例如,更改。

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

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


确定当前 console的活动 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-less UTF-8 用于其 cmdlet,但在 Windows 上,活动 OEM 代码页(如 中所示)在[Console]::OutputEncoding外部程序


推荐阅读