简体   繁体   中英

PowerShell scope of changes in lines with multiple commands - UICulture

During my tinkering with PS 5.1 related to the objective of question Fully change language for the current PowerShell session I observed a "strange" behavior:

> [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)

(the function above was obtained from here ). Replacing [system.threading.thread]::currentthread. with [cultureinfo]:: everywhere produced exactly the same results.

What I found strange is:

  1. I conclude that the boundary of a "thread" (the currentthread) appears to be the execution command line.
    Nevertheless, here it is quoted as "a session-scoped (non-persistent) solution" (in response to its OP Temporarily change powershell language to English? ). That answer even posted a wrapper function to limit the scope of the change to the executing command.
    This information apparently opposes this , which states " [Threading.Thread]::CurrentThread.CurrentUICulture only affects to current one-liner" (coinciding with my conclusion).

  2. I can obtain an immediate change of Culture for just that one "thread", even if Set-Culture only takes effect after launching a new session.
    I might conclude that's how it works.

How can these two points be rationalized? (I would welcome authoritative documentation).

Due to a bug in Windows PowerShell [1] (PowerShell [Core] v6+ is not affected), in-session changes to [cultureinfo]::CurrentUICulture and [cultureinfo]::CurrentCulture are automatically reset to the values at startup time [2] at the command prompt, whenever a command finishes executing .

Trying to modify the culture(s) in $PROFILE is equally affected, unfortunately.

However, for a given script, in-script culture changes remain in effect for the entire script as well as its callees (on the main thread) - see this answer .

There are two possible workarounds :

  • Use reflection to modify the non-public field where Windows PowerShell stores the start-up culture value(s) - see this answer .

    • Note: Modifying non-public fields is generally ill-advised, but should be fine in this case, given that Windows PowerShell will see no new development; however, note that $PSUICulture / $PSCulture will not reflect the culture put into effect by the workaround - use [cultureinfo]::CurrentCulture / [cultureinfo]::CurrentUICulture instead.
  • Alternatively, change the current user's OS-level language / locale settings before starting PowerShell :

    • Programmatically,

      • you can change the current user's display language ( UI culture , reflected in [cultureinfo]::CurrentUICulture ) with Set-WinUILanguageOverride

      • you can change the locale ( culture , reflected in [cultureinfo]::CurrentCulture ) with Set-Culture

      • Note that both commands require at least Windows 8 / Windows Server 2012 R2 and that Set-WinUILanguageOverride requires a logoff of reboot to take effect, while Set-Culture changes only take effect in future sessions (but don't require a logoff / reboot).


[1] There is no official bug report I am aware of, but the following factors lead me to classify Windows PowerShell's behavior as a bug : The behavior is counterintuitive, cannot be avoided other than via 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 : "I forget exact details, but the current culture is reset for reasons I never understood."

[2] The values at startup of the PowerShell process, as determined by the user's OS-level display language and locale settings (regional format).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM