写入信息似乎不适用于 powershell foreach-object -parallel

tco*_*unk 9 parallel-processing powershell output foreach-object powershell-7.0

我是 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"       
        }
}
Run Code Online (Sandbox Code Playgroud)

函数调用如下:writeTest -verbose

输出:

host
Output
WARNING: Warning
Write-Error: error
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么 write-verbose 和 write-information 不显示任何内容?

如有无知之处请原谅。

mkl*_*nt0 9

您在ForEach-Object -Parallel/中看到一个错误Start-ThreadJob,至少在 PowerShell Core 7.0 中存在:

您的Write-Information输出应该显示,因为您曾经-InformationAction Continue打开过它;虽然您的Write-Verbose输出不会显示是预料之中的,因为您没有使用 来打开它,但由于该错误,-Verbose如果您确实使用了 ,它也不会显示。-Verbose

请参阅GitHub 问题 #13816

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

另外,您的代码存在一个概念问题:

  • 您将-Verbose公共参数传递给write-Test函数,但该函数未声明为高级函数(它需要块[CmdletBinding()]上方的属性param(...)和/或至少一个带有[Parameter(...)]属性的参数 - 请参阅about_Functions_Advanced),因此该参数将具有没有效果。

  • 即使它确实生效,这意味着 PowerShell 将其转换为$VerbosePreference带有 value 的函数局部变量'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
Run Code Online (Sandbox Code Playgroud)

请注意传递给开关的表达式,必须用- --Verbose与开关名称分开,如果函数的主线程 ( ) 中的值设置为,则实际上仅打开详细输出,而这又在传递给高级时发生。从外部调用函数(由于 PowerShell 的动态作用域,如果设置为调用者的作用域,也会发生这种情况;请参阅此答案)。:-Verbose:($using:VerbosePreference -eq 'Continue')$VerbosePreference$using:'Continue'-Verbose$VerbosePreference'Continue'


有关 PowerShell 输出流的一般信息

  • 默认情况下,和都是静默Write-Verbose的。Write-InformationWrite-Debug

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

    • 每个命令,通过一个通用参数:添加-Verbose到一个Write-Verbose调用和InformationAction Continue一个Write-Information调用(正如您所做的那样)。

    • 在范围范围内,通过首选项变量:设置$VerbosePreference = 'Continue'$InformationPreference = 'Continue'- 但需要注意的是,默认情况下,(其他)模块中的函数和在不同线程或进程中运行的代码都看不到这些变量:

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

请参阅about_Redirectionabout_CommonParametersabout_Preference_Variables