如何从-Wha​​tIf处理中排除块?

时间:2016-03-29 17:58:40

标签: powershell

我正在编写一个Powershell cmdlet,它需要执行命令并将其stderr输出存储到临时文件中以供以后处理。此输出列出了cmdlet稍后可能使用的COM端口。

# mostly side-effect-free information gathering
$info = [IO.Path]::GetTempFileName()
info-gather.exe 2>$info
Get-Content $info | ForEach-Object {
    # processing
}
Remove-Item $info

# serious things with serious side effects start here

我希望这个cmdlet能够实现-WhatIf,因为它会产生非平凡的副作用。但是,-WhatIf行为将接管info-gather.exe命令,并且它永远不会被执行。相反,它打印:

  

如果:在目标“temp \ path \ to \ tmp78A4.tmp”上执行“输出到文件”操作

因为永远不会执行此命令,所以内部处理也不会发生,并且我的cmdlet的其余部分都没有执行,因为它不知道要使用哪些端口,因此{{1}很大程度上没用。

如何在不阻止cmdlet其余部分的情况下绕过此块的-WhatIf

2 个答案:

答案 0 :(得分:2)

您可以使用try...finally设置然后重置$WhatIfPreference variable

$script:oldWhatIfPrefernence = $WhatIfPreference
try {
    $WhatIfPreference = $false

    $info = [IO.Path]::GetTempFileName()
    info-gather.exe 2>$info
    Get-Content $info | ForEach-Object {
        # processing
    }
    Remove-Item $info
} finally {
    $WhatIfPreference = $script:oldWhatIfPreference
}

如果您没有使用2>重定向,还有另一种方法。您可以明确地将-WhatIf开关传递给多个cmdlet,并仅覆盖-WhatIf部分。

Remove-Item $info -WhatIf:$false

尽管如此,zneak's answer不涉及临时文件也非常优雅。

答案 1 :(得分:1)

一种解决方案是"重定向" stderr到stdout。执行此操作,Powershell将错误记录附加到标准输出,可以使用Out-String将其转换为常规字符串。在我的情况下(YMMV取决于程序),第一个错误记录显示"该程序出现错误"第二个错误记录是实际的完整stderr输出。命令不会向标准输出写入任何内容,这也简化了这一点,因此无法进行过滤。

我能够改变foreach循环来使用它:

((info-gather.exe 2>&1)[1] | Out-String) -split "[`r`n]" | foreach-object

由于这不会写入文件,-WhatIf不再覆盖它。

可能有一种更简单,更简洁的方法(例如,如果有办法将stderr直接传递给Out-String)。