PowerShell 多命令行的变化范围 - UICulture

PowerShell scope of changes in lines with multiple commands - UICulture

在我修改 PS 5.1 期间,与问题 的 objective 有关 我观察到一个“奇怪”的行为:

> [system.threading.thread]::currentthread.currentculture ; [system.threading.thread]::currentthread.currentuiculture ;
LCID             Name             DisplayName
----             ----             -----------
1033             en-US            English (United States)
1033             en-US            English (United States)
> function Set-CultureWin([System.Globalization.CultureInfo] $culture) { [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture ; [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture } ; Set-CultureWin es-ES ; [system.threading.thread]::currentthread.currentculture ; [system.threading.thread]::currentthread.currentuiculture ;
LCID             Name             DisplayName
----             ----             -----------
3082             es-ES            Español (España)
3082             es-ES            Español (España)
> [system.threading.thread]::currentthread.currentculture ; [system.threading.thread]::currentthread.currentuiculture ;
LCID             Name             DisplayName
----             ----             -----------
1033             en-US            English (United States)
1033             en-US            English (United States)

(上面的函数是从中得到的)。 在任何地方用 [cultureinfo]:: 替换 [system.threading.thread]::currentthread. 都会产生完全相同的结果。

我觉得奇怪的是:

  1. 我断定一个“线程”(当前线程)的边界似乎是执行命令行。
    尽管如此, it is quoted as "a session-scoped (non-persistent) solution" (in response to its OP )。 该答案甚至发布了一个包装函数来限制对执行命令的更改范围。
    此信息显然反对 this,其中指出“[Threading.Thread]::CurrentThread.CurrentUICulture 仅影响当前单行”(与我的结论一致)。

  2. 即使 Set-Culture 仅在启动新会话后才生效,我也可以立即为那个“线程”获得 Culture 的更改。
    我可能会得出这样的结论。

这两点如何合理化? (我会欢迎权威文档)。

由于 错误 Windows PowerShell[1](PowerShell [Core] v6+ 受影响),会话中更改为 [cultureinfo]::CurrentUICulture[cultureinfo]::CurrentCulture 在启动时 自动重置 [2] 在命令提示符下,每当命令完成执行.

不幸的是,尝试修改 $PROFILE 中的区域性同样受到影响。

但是,对于给定的脚本,脚本中 文化更改对整个脚本及其调用者(在主线程上)仍然有效 - 参见 .

有两种可能的解决方法

  • 使用反射修改 Windows PowerShell 存储启动文化值的非 public 字段 - 见 this answer.

    • 注意:修改非 public 字段通常是不明智的,但在这种情况下应该没问题,因为 Windows PowerShell 不会看到新的发展;但是,请注意 $PSUICulture / $PSCulture 不会 反映变通方法生效的文化 - 请改用 [cultureinfo]::CurrentCulture / [cultureinfo]::CurrentUICulture .
  • 或者,更改当前用户的OS级别语言/区域设置之前 启动 PowerShell:

    • 以编程方式,

      • 您可以更改当前用户的显示语言UI文化,反映在[cultureinfo]::CurrentUICulture) 与 Set-WinUILanguageOverride

      • 您可以更改 localeculture,反映在 [cultureinfo]::CurrentCulture)与 Set-Culture

      • 请注意,这两个命令至少需要 Windows 8 / Windows Server 2012 R2 并且 Set-WinUILanguageOverride 需要注销重启才能生效,而 Set-Culture 更改仅在 未来 会话中生效(但不需要注销/重启)。


[1] 据我所知,没有正式的错误报告,但以下因素使我将 Windows PowerShell 的行为归类为 错误:这种行为是违反直觉的,除了通过 a hack, and has been corrected in PowerShell [Core] v6+. Also, a core member of the PowerShell team had this to say in this GitHub issue 之外无法避免:“我忘记了确切的细节,但由于我从未理解的原因,当前的文化被重置了。”

[2] PowerShell 进程启动时的值,由用户的 OS 级显示语言和区域设置决定(区域格式)。