簡體   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