繁体   English   中英

PowerShell - 从 Invoke-Command 内部调用时,ShouldProcess 不起作用

[英]PowerShell - ShouldProcess not working when called from inside Invoke-Command

我正在尝试将 ShouldProcess 逻辑添加到删除远程服务器上的文件的脚本中,以便我可以使用 -WhatIf 参数,但它返回错误。 这是函数:

function testshouldprocess {
    [CmdletBinding(SupportsShouldProcess = $true]
    param(
        $server
    )
        invoke-command $server {
        Get-ChildItem c:\temp\ | ForEach-Object {
            if($pscmdlet.ShouldProcess($Server)) {
                remove-item $_.fullname
            }
        }
    }
}
testshouldprocess 'Server1' -WhatIf

当脚本运行时,它返回错误

InvalidOperation: You cannot call a method on a null-valued expression.

当每个文件通过管道时。 如果我将代码更改为

  if ($pscmdlet.ShouldProcess($server)) {
        invoke-command $server {
            Get-ChildItem c:\temp\ | ForEach-Object {
                remove-item $_.fullname
            }
        }
    }

它有效,但 WhatIf 只对整个目录列表执行一次。 如果我将代码更改为

Get-ChildItem \\$server\c$\temp\ | ForEach-Object {
        if ($pscmdlet.ShouldProcess($server)) {
            remove-item $_.fullname
        }
    }

它有效,但我更喜欢使用 Invoke-Command。

ShouldProcess 与 Invoke-Command 不兼容吗?

任何见解表示赞赏。

远程服务器只知道您执行的命令。 不是来自远程调用者的值。 尝试使用remove-item $_.fullname -Whatif:$($using:pscmdlet.ShouldProcess($server)) 请参阅远程变量另一种选择是在远程服务器上指定$WhatIfPreference并在接下来的语句中使用它$WhatIfPreference = $using:pscmdlet.ShouldProcess($server); 然后remove-item $_.fullname -WhatIf:$WhatIfPreference

Hazrelle 的回答提供了关于需要使用$using:范围以便远程执行脚本块能够访问来自调用者范围的值的关键指针。

为了完全支持您的方案 - 对于-WhatIf-Confirm功能,这两者都通过打开SupportShouldProces来暗示 - 您必须:

  • 使您的远程执行脚本块也成为高级脚本块,在param()块上方有自己的[CmdletBinding(SupportsShouldProcess)]属性,因此也有自己的$PSCmdlet实例。

  • 通过$using:WhatIfPreference$using:ConfirmPreference调用者的范围中引用假设/确认相关值

    • 请注意,对于高级函数和脚本,PowerShell 使用函数局部变量将-WhatIf-Confirm开关转换为等效的首选项变量值; 也就是说,传递-WhatIf创建一个值为$true的函数局部$WhatIfPreference变量,传递-Confirm创建一个值为High的函数局部$ConfirmPreference变量。
function testshouldprocess {
  [CmdletBinding(SupportsShouldProcess)]
  param(
    $server
  )

  Invoke-Command $server {
    [CmdletBinding(SupportsShouldProcess)]
    param()

    # Use the caller's WhatIf / Confirm preferences.
    $WhatIfPreference = $using:WhatIfPreference
    $ConfirmPreference = $using:ConfirmPreference

    Get-ChildItem c:\temp\ | ForEach-Object {
      if ($pscmdlet.ShouldProcess($using:server, "delete file: $($_.FullName)")) {
        Remove-Item $_.FullName
      }
    }
  }

}

testshouldprocess 'Server1' -WhatIf

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM