如何处理 ForEach-Object -Parallel 脚本块中的 -WhatIf

问题描述 投票:0回答:1

有一个脚本具有

CmdletBinding
属性,这实际上使其成为“高级”脚本。在脚本内部,我正在并行处理管道中的数据,并且当我将
-WhatIf
参数传递给脚本调用时,我希望将其传递到处理脚本块。

简化代码:

#Requires -Version 7.2
[CmdletBinding(SupportsShouldProcess = $true)]
param()

Get-ChildItem | ForEach-Object -Parallel {
    if ($PSCmdlet.ShouldProcess("target", "operation")) {
        Write-Host "Processing"
    }
}
PS C:\> script.ps1 -WhatIf
InvalidOperation: 
Line |
   2 |      if ($PSCmdlet.ShouldProcess("target", "operation")) {
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression.

这不起作用,因为脚本块中未定义

$PSCmdlet

当我将

$PSCmdlet
替换为
($using:PSCmdlet)
时,我收到另一个错误(仅当提供
-WhatIf
时):

MethodInvocationException: 
Line |
   2 |      if (($using:PSCmdlet).ShouldProcess("target", "operation")) {
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Exception calling "ShouldProcess" with "2" argument(s): "The WriteObject and WriteError methods cannot be called from outside the overrides of the BeginProcessing, ProcessRecord, and EndProcessing methods, and they can only be called from within the same thread. Validate that the cmdlet makes these calls correctly, 
or contact Microsoft Customer Support Services."

显然,发生这种情况是因为脚本块是在单独的线程中执行的(“它们只能从同一线程内调用”)。

如何正确处理

-WhatIf
脚本块内的
Foreach-Object -Parallel

我已阅读 这篇官方文章 并看到 对 PowerShell 问题 #13816 的评论。也许另一个相关问题:#14984

作为旁注:在这种情况下,将

-WhatIf
指定为
ForEach-Object
本身并没有任何区别。这里也注意到了这一点:https://thedavecarroll.com/powershell/foreach-object-whatif/#script-blocks-and--whatif

powershell foreach-object
1个回答
1
投票

我能得到的最接近工作的东西,正如你所看到的,它非常麻烦。首先,如上所述,风险管理参数似乎不适用于

ForEach-Object -Parallel
Start-ThreadJob
。使用这个答案中的功能,
-WhatIf
似乎可以正常工作,但是解决方法确实需要内部脚本块也支持
SupportsShouldProcess

这就是代码的样子:

[CmdletBinding(SupportsShouldProcess)]
param()

Get-ChildItem | Invoke-Parallel {
    & {
        [CmdletBinding(SupportsShouldProcess)]
        param()
        if ($PSCmdlet.ShouldProcess($_, "doing something")) {
            Write-Host "Processing"
        }
    } -WhatIf:([bool] $using:PSBoundParameters['WhatIf'])
}
© www.soinside.com 2019 - 2024. All rights reserved.