问题描述
我是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"
}
}
输出:
host
Output
WARNING: Warning
Write-Error: error
请原谅任何无知。
解决方法
您在ForEach-Object -Parallel
/ Start-ThreadJob
中看到了一个 bug ,至少出现在PowerShell Core 7.0中:
应该显示您的Write-Information
输出 ,因为您已经使用-InformationAction Continue
将其打开;虽然您的Write-Verbose
输出未显示是预期的,因为您没有使用-Verbose
将其打开,但由于该错误,它也不会显示是否使用了-Verbose
。
解决方法是要还设置首选项变量 $InformationPreference
,以便在调用{之前打开信息流{1}}(请参见下文)。
另外,您的代码存在概念上的问题:
-
您正在将
ForEach-Object -Parallel
通用参数传递给-Verbose
函数,但是该函数并未声明为 advanced 函数(它需要一个{write-Test
块上方的{1}}属性和/或至少一个具有[CmdletBinding()]
属性的参数-请参见about_Functions_Advanced),因此该参数无效。 -
即使它确实生效,这也意味着PowerShell将其转换为具有值
param(...)
的函数局部[Parameter(...)]
变量,$VerbosePreference
块也不会看到该变量,因为需要'Continue'
范围来引用调用者范围中的变量值;参见this answer。
将它们放在一起。
ForEach-Object -Parallel
请注意传递给$using:
开关的 expression ,必要时用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')
值设置为$VerbosePreference
,则输出,当$using:
从外部传递给高级函数时,会发生这种情况(如果由于PowerShell的动态作用域,在调用者的范围内将'Continue'
设置为-Verbose
,也会发生这种情况;请参阅this answer)。
有关PowerShell输出流的常规信息:
-
$VerbosePreference
和'Continue'
都默认为沉默,Write-Verbose
也是如此。 -
您可以通过以下两种方式之一显示其输出:
-
每个命令,通过公用参数:将
Write-Information
添加到Write-Debug
调用中,将-Verbose
添加到Write-Verbose
调用中(完成操作)。 -
范围内,通过首选项变量:设置
InformationAction Continue
和Write-Information
-但是 caveat 是没有一个函数有效在(其他)模块中的 或在其他线程或进程中运行的代码都默认情况下会看到以下变量:- 在模块情况下,您必须显式使用公共参数,或者在 global 范围内设置首选项变量,这是不可取的。问题在GitHub issue #4568中进行了讨论。
- 在其他线程/进程情况下,需要
$VerbosePreference = 'Continue'
范围,如上所示。
-
请参见about_Redirection,about_CommonParameters和about_Preference_Variables