可以使用 -WhatIf 和调用运算符 (&) 吗?

Possible to use -WhatIf and the invocation operator (&)?

是否可以在执行外部命令时使用-WhatIf参数?我希望能够 运行 带有 -WhatIf 的脚本,并让它打印出所有外部命令和参数的完整列表 运行 而实际上 运行 宁他们。

我尝试过如下操作:

Function Invoke-Checked
{
    param([ScriptBlock]$s)

    if ($PSCmdlet.ShouldProcess($s.ToString(), "Execute"))
    {
        Invoke-Command $s
    }
}

但这不会扩展脚本块中存在的任何变量 - 执行如下操作:

$s = { & dir $test }
Invoke-Checked $s

只是打印

Performing the operation "Execute" on target " & dir $test ".

不是特别有用。

有什么方法可以做我想做的事吗?

首先 - 您需要确保您的 'wrapper' 函数支持 WhatIf。 另一件事:您可以扩展 scriptBlock,但我不太相信这样做是明智的:例如如果$test = 'Some path with spaces',展开后会停止工作

话虽这么说:这里有两个对我有用的选项:在 scriptBlock 上使用 GetNewClosure() 方法,并扩展整个东西:

function Invoke-ExpandedChecked {
[CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'Medium'
)]
    param([ScriptBlock]$ScriptBlock)

    $expanded = $ExecutionContext.InvokeCommand.ExpandString($ScriptBlock)
    $script = [scriptblock]::Create($expanded)
    if ($PSCmdlet.ShouldProcess($script.ToString(), "Execute"))
    {
        & $script
    }
}

function Invoke-Checked {
[CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'Medium'
)]
    param([ScriptBlock]$ScriptBlock)

    $newClosure = $ScriptBlock.GetNewClosure()
    if ($PSCmdlet.ShouldProcess($newClosure.ToString(), "Execute"))
    {
        & $newClosure
    }
}

$test = '.\DSCDemo.ps_'
$s = { cmd /c dir $test} 

Invoke-Checked $s -WhatIf
Invoke-Checked $s
Invoke-ExpandedChecked $s -WhatIf
Invoke-ExpandedChecked $s

以及带空格的路径的结果示例:

$test = 'C:\Program Files'
Invoke-Checked $s
Invoke-ExpandedChecked $s

对于带有新外壳的人来说效果很好。随着展开:

cmd : File Not Found
At line:1 char:2
+  cmd /c dir C:\Program Files

我将把这个问题解释为“我如何将 -whatif 与 运行 外部命令一起使用?”,因为这就是我发现这个问题的方式。

# myscript.ps1
[cmdletbinding(SupportsShouldProcess=$True)]
Param($path)  # put Param() if no parameters

if ($pscmdlet.ShouldProcess($Path, 'creating folder')) { # not -whatif
  cmd /c mkdir $path
}
.\myscript foo -whatif
What if: Performing the operation "creating folder" on target "foo".