【问题标题】:Temporarily change powershell language to English?暂时将powershell语言更改为英语?
【发布时间】:2021-12-10 05:50:56
【问题描述】:

我编写了一些使用系统(powershell)命令输出的软件,但没有预见到除英语以外的其他语言的输出会有所不同。

有没有办法将 Powershell 中的语言临时更改为英语只针对那个单一的 Powershell 会话

注意事项

  • 如果它很重要,我希望运行的特定 powershell 代码是 netstat -n -a

  • 我遇到了一些更改 powershell 语言的方法(例如herehere)。但我要小心不要永久更改它! (那会很糟糕)

【问题讨论】:

  • netstat 不是 powershell cmdlet - 它是一个可执行文件。为什么不在 powershell 脚本中使用Get-NetTCPConnection

标签: powershell


【解决方案1】:
  • (a) 对于外部程序,例如netstat.exe,不幸的是,没有方法(据我所知)可以更改 UI 语言会话中

    • 在 Windows Server 2012 / Windows 8 及更高版本上,Set-WinUILanguageOverride cmdlet 允许您(持久地)为当前用户更改系统范围的 UI 语言,但这仅在未来登录会话中生效 - 也就是说,需要注销并重新登录或重新启动

    • 顺便说一句:在 Windows Server 2012 / Windows 8 及更高版本上,还有 Set-Culture cmdlet,但其目的不会改变UI 文化(显示语言),但仅限于特定于文化的设置,例如日期、数字和货币格式。它也会持久地更改当前用户的设置,但只需要一个新的会话(进程)才能使更改生效。

  • (b) 对于 PowerShell 命令.NET 类型一个会话中(非持久)解决方案 - 假设命令是文化感知的并带有本地化字符串

注意事项

  • PowerShell [Core] 本身在 v7.0尚未本地化; this GitHub issue 中正在跟踪进度;但是,以下解决方案确实适用于附带本地化消息和帮助内容的第三方模块。

  • 由于 Windows PowerShell 中的一个错误(PowerShell [Core] v6+ 受影响),会话中更改为[cultureinfo]::CurrentUICulture[cultureinfo]::CurrentCulture 在命令提示符处自动重置,只要命令完成执行;但是,对于给定脚本,更改对整个脚本及其被调用者仍然有效 - 请参阅 this answer


退后一步:

我编写了一些使用系统(powershell)命令输出的软件,但没有预见到除英语以外的其他语言的输出会有所不同。

这正是通常值得寻找PowerShell-native解决方案而不是调用外部程序的原因:

不必解析 - 可能是本地化的 - 文本,例如 netstat.exe,PowerShell 命令返回 对象,您可以可靠地访问其属性以独立于文化的方式。

具体来说,Mathias R. Jessen 建议将Get-NetTCPConnection 视为netstat.exe 的PowerShell 替代品(适用于Windows Server 2012 / Windows 8 及更高版本)。


为了帮助解决 (b),下面是 helper 函数 Use-Culture,您可以按如下方式使用它来执行给定的脚本块 ({ ... })给定 (UI) 文化的背景:

# Windows PowerShell: emit an error message in *French* (culture 'fr-FR')
# Note: Does not yet work as of PowerShell [Core] 7.0
PS> Use-Culture fr-FR { try { 1/0 } catch { "Localized message: $_" } }
Localized message: Tentative de division par zéro.

请注意,文化和 UI 文化的文化变化是命令范围的;也就是说,在命令完成后,之前的设置再次生效。


函数Use-Culture的源代码:

注意:代码改编自this venerable blog post

# Runs a script block in the context of the specified culture, without changing 
# the session's culture persistently.
# Handy for quickly testing the behavior of a command in the context of a different culture.
# Example: 
#   Use-Culture fr-FR { Get-Date }
function Use-Culture
{    
  param(
    [Parameter(Mandatory)] [cultureinfo] $Culture,
    [Parameter(Mandatory)] [scriptblock] $ScriptBlock
  )
  # Note: In Windows 10, a culture-info object can be created from *any* string.
  #        However, an identifier that does't refer to a *predefined* culture is 
  #        reflected in .LCID containing 4096 (0x1000)
  if ($Culture.LCID -eq 4096) { Throw "Unrecognized culture: $($Culture.DisplayName)" }

  # Save the current culture / UI culture values.
  $PrevCultures = [Threading.Thread]::CurrentThread.CurrentCulture, [Threading.Thread]::CurrentThread.CurrentUICulture

  try {
    # (Temporarily) set the culture and UI culture for the current thread.
    [Threading.Thread]::CurrentThread.CurrentCulture = [Threading.Thread]::CurrentThread.CurrentUICulture = $Culture

    # Now invoke the given code.
    & $ScriptBlock

  }    
  finally {
    # Restore the previous culture / UI culture values.
    [Threading.Thread]::CurrentThread.CurrentCulture = $PrevCultures[0]
    [Threading.Thread]::CurrentThread.CurrentUICulture = $PrevCultures[1]
  }
}

【讨论】:

【解决方案2】:

此代码的原始作者是@Sceptalist。

从 powershell 控制台运行它。它将当前会话的文化更改为 en-US。

function Set-CultureWin([System.Globalization.CultureInfo] $culture) { [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture ; [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture } ; Set-CultureWin en-US ; [system.threading.thread]::currentthread.currentculture

那么你必须使用命令Get-NetTCPConnection 而不是netstat。用法见https://docs.microsoft.com/en-us/powershell/module/nettcpip/get-nettcpconnection?view=win10-ps

【讨论】:

  • 谢谢,看起来很有希望。我将在可以访问 Windows 框后立即进行测试。你知道Get-NetTCPConnection的输出是否和netstat完全一样吗?
  • 是的,该 cmdlet 的输出比 netstat 更加广泛和有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多