在 PowerShell 的 foreach-object -parallel 中,Write-Information 似乎无法正常工作。

9

我刚接触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不显示任何内容?
请原谅我的无知。

默认情况下,这两个流不会被显示。可以通过类似 Get-Variable -Name *prefer* 的命令查看相应的首选项 $ 变量... [咧嘴笑] - Lee_Dailey
1个回答

9
您在使用至少 PowerShell Core 7.0 版本中的 ForEach-Object -Parallel / Start-ThreadJob 时遇到了一个错误

您使用了 -InformationAction Continue 命令来开启信息流,因此您的 Write-Information 输出应该会显示出来。但是您没有使用 -Verbose 命令来开启冗余流,所以您的 Write-Verbose 输出不会显示,即使您使用了 -Verbose 命令也不会显示,这是由于该错误导致的。

请参见 GitHub issue #13816

解决方法是在调用 ForEach-Object -Parallel 之前还要设置 偏好变量 $InformationPreference 以开启信息流(如下所示)。

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

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

  • 即使它生效了,这意味着 PowerShell 将其转换为函数局部的 $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' 时打开详细输出,并且只有从外部传递 -Verbose 到高级函数时才会发生这种情况(如果在调用者范围内将 $VerbosePreference 设置为 'Continue' ,也是一样的,这是因为 PowerShell 具有动态作用域; 请参见此答案)。

PowerShell 输出流的一般信息:

  • 默认情况下,Write-VerboseWrite-InformationWrite-Debug 都是 沉默的

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

    • 对于每个命令,通过通用参数:向Write-Verbose 调用添加 -Verbose,并向Write-Information 调用添加 InformationAction Continue(就像您已经做的那样)。

    • 通过首选项变量来控制整个作用域:设置 $VerbosePreference = 'Continue'$InformationPreference ='Continue'。但是,注意,不属于模块的函数和在不同线程或进程中运行的代码默认情况下无法看到这些变量:

      • 对于模块,请显式使用通用参数或在全局范围内设置首选项变量,但这是不建议的;此问题已在GitHub issue #4568中讨论过。
      • 对于其他线程/进程,请使用 $using: 作用域,如上例所示。

请参见about_Redirectionabout_CommonParametersabout_Preference_Variables


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接