写入信息在 powershell foreach-object -parallel 中似乎不起作用

Write-Information does not appear to work in powershell foreach-object -parallel

我是 powershell 的新手,刚刚开始学习。我有一些 C# 经验。我正在尝试使用 foreach-object -Parallel 选项,但无法使所有 Write-* 函数正常工作。

function writeTest {
        1..1 | ForEach-Object -Parallel {
            Write-Host "host"
            Write-Output "Output"
            Write-Information "information" -InformationAction Continue
            Write-Verbose "verbose"
            Write-Warning "Warning"
            Write-Error "error"       
        }
}

函数调用如下:writeTest -verbose

输出:

host
Output
WARNING: Warning
Write-Error: error

我的问题是为什么 write-verbose 和 write-information 什么都不显示?

不明之处还请见谅

您在 ForEach-Object -Parallel / Start-ThreadJob 中看到 bug,至少出现在 PowerShell核心 7.0:

你的Write-Information输出应该显示,因为你已经使用-InformationAction Continue打开它;虽然你的 Write-Verbose 输出不显示是预期的,因为你没有用 -Verbose 打开它,如果你确实使用 -Verbose,它也不会显示,由于错误。

GitHub issue #13816

解决方法设置首选项变量 $InformationPreference在调用 ForEach-Object -Parallel(见下文)之前,为了打开信息流。

另外,您的代码存在概念性问题

  • 您将 -Verbose 公共参数传递给您的 write-Test 函数,但此函数未声明为 高级 函数(它需要一个 [CmdletBinding()] 属性在 param(...) 块之上 and/or 至少一个具有 [Parameter(...)] 属性的参数 - 见 about_Functions_Advanced),所以参数将没有效果。

  • 即使它确实生效了,这意味着 PowerShell 将其转换为 function-local $VerbosePreference 值为 'Continue' 的变量,ForEach-Object -Parallel 不会 看到该变量,因为需要 $using: 作用域来引用调用者作用域中的变量值;参见

把它们放在一起。

function Write-Test {

  # Mark the function as an advanced one, so that it accepts 
  # common parameters such as -Verbose
  [CmdletBinding()]
  param()
  
  # WORKAROUND: Turn the information stream on 
  #             via its *preference variable* AS WELL:
  $InformationPreference = 'Continue'
  
  1..1 | ForEach-Object -Parallel {
    Write-Host "host"
    Write-Output "Output"
    Write-Information "information" -InformationAction Continue               
    Write-Verbose "verbose" -Verbose:($using:VerbosePreference -eq 'Continue')
    Write-Warning "Warning"
    Write-Error "error"       
  }

}
  
Write-Test -Verbose

请注意传递给 -Verbose 开关的 表达式 ,必须用 : - -Verbose:($using:VerbosePreference -eq 'Continue') 与开关名称分开 - 在如果函数主线程 ($using:) 中的 $VerbosePreference 值设置为 'Continue',则 effect 只会打开详细输出,这反过来会在 -Verbose 传递给高级时发生从外部运行(由于 PowerShell 的动态作用域,如果在 调用者的 范围内将 $VerbosePreference 设置为 'Continue' 也会发生这种情况;参见 ).


有关 PowerShell 输出流的一般信息:

  • Write-VerboseWrite-Information默认静音Write-Debug

  • 您可以通过以下两种方式之一显示它们的输出:

    • Per-command,通过 公共参数 :将 -Verbose 添加到 Write-Verbose 调用,并且 InformationAction ContinueWrite-Information 电话(正如您所做的那样)。

    • Scope-wide,通过 偏好变量 :设置 $VerbosePreference = 'Continue'$InformationPreference = 'Continue' - 但 警告 是(其他)模块 中的函数和在不同线程或进程中运行的代码 都看不到这些变量默认:

      • 在模块情况下,您必须显式使用公共参数或在全局范围内设置首选项变量,这是不可取的; GitHub issue #4568.
      • 中讨论了该问题
      • 在另一种 thread/process 情况下,$using: 范围是必需的,如上所示。

about_Redirection, about_CommonParameters, and about_Preference_Variables