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

2cmtqfgy  于 2023-01-20  发布在  Shell
关注(0)|答案(1)|浏览(153)

有一个脚本具有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
当我用($using:PSCmdlet)替换$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."

显然,这是因为脚本块是在seaprate线程中执行的("它们只能从同一个线程中调用")。

    • 如何正确处理Foreach-Object -Parallel脚本块中的-WhatIf?**

我读过this official article,看到了PowerShell问题#13816的评论。可能是另一个相关问题:#14984.
作为旁注:在这种情况下,将-WhatIf指定为ForEach-Object本身不会产生任何影响。www.example.comhttps://thedavecarroll.com/powershell/foreach-object-whatif/#script-blocks-and--whatif

p4tfgftt

p4tfgftt1#

正如你所看到的,我所能得到的最接近工作的东西是非常麻烦的。首先,如前所述,风险管理参数似乎在ForEach-Object -ParallelStart-ThreadJob中都不工作。使用this answer中的函数,-WhatIf似乎工作正常,但是变通方案确实需要一个内部脚本块也支持SupportsShouldProcess
代码如下所示:

[CmdletBinding(SupportsShouldProcess)]
param()

Get-ChildItem | Invoke-Parallel {
    & {
        [CmdletBinding(SupportsShouldProcess)]
        param()
        if ($PSCmdlet.ShouldProcess($_, "doing something")) {
            Write-Host "Processing"
        }
    } -WhatIf:$WhatIf
} -Variables @{ WhatIf = [bool] $PSBoundParameters['WhatIf'] }

相关问题