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

Script to detect if Windows System Locale is using UTF-8 code page?

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

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

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

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

当我在 Win10 上尝试使用 'beta' 非 unicode 程序的美式英语 utf-8 支持时,WMI 继续报告代码页为 1252。尽管这显然不是这种情况(代码页 1252 的代码点为 128,但 none 为 49800:UTF-8 的代码点为 49800,none 为 128)。

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

PowerShell(基于shell)解决方案:

确定系统区域设置的(系统范围)OEM代码页 - [=56使用的代码页] =]控制台应用程序,使用注册表:

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

注:

  • 使用 还将 ANSI 代码页 (ACP) 设置为 65001,供 旧版 GUI 应用程序使用 但值得注意的是 Windows PowerShell[1],意味着 Windows PowerShell 的默认编码 Get-ContentSet-Content cmdlet,例如,更改。

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

  • 请注意,遗憾的是,PowerShell 的 Get-WinSystemLocale cmdlet cannot be used as of this writing, because the [cultureinfo] instance it returns does not reflect a UTF-8 override that may be in place - see this ServerFault answer.


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

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

注:

  • 您可以从 cmd.exe 执行 chcp chcp.com,但您随后必须解析其文本输出以仅提取代码页码

基于

WindowsAPI的解决方案:

从已编译的应用程序中,您可以使用 GetACP() and 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()

注:

  • 如果您编译的应用程序是 console 应用程序并且您想知道 相关控制台的当前 OEM 代码页 - 这可能会或可能不是通过系统语言环境设置的默认页面 - 请改用 GetConsoleOutputCP() 函数。

[1] 活动的 ANSI 代码页不再与 PowerShell [Core] v6+ 相关,它始终使用无 BOM 的 UTF-8 作为其cmdlet,但在 Windows 活动的 OEM 代码页上,如 [Console]::OutputEncoding 所示,在与 外部程序.[=30 通信时仍然很重要=]