I'm writing a Powershell cmdlet that needs to execute a command and store its stderr output to a temporary file for later processing. This output lists COM ports that the cmdlet may use later.
# 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
I would like this cmdlet to implement -WhatIf
since it will have non-trivial side effects. However, the -WhatIf
behavior takes over the info-gather.exe
command and it is simply never executed. Instead, it prints:
What if: Performing the operation "Output to File" on target "temp\path\to\tmp78A4.tmp"
Because this command is never executed, the inner processing doesn't happen either, and the rest of my cmdlet that has actual side effects isn't executed because it doesn't know which ports to use, making -WhatIf
largely useless.
How can I bypass -WhatIf
for this block without overriding it in the rest of the cmdlet?
You could use try...finally
to set and then reset the $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
}
If you weren't using the 2>
redirection, there is another way. You can pass the -WhatIf
switch explicitly to many cmdlets and override -WhatIf
for just that part.
Remove-Item $info -WhatIf:$false
Though, zneak's answer that doesn't involve a temporary file is pretty elegant too.
One solution is to "redirect" stderr to stdout. Doing this, Powershell appends error records to the standard output, which can be converted to regular strings using Out-String
. In my case (YMMV depending on the program), the first error record says "there was an error with this program" and the second error record is the actual, full stderr output. This is also simplified by the fact that the command doesn't write anything to the standard output, so there's no filtering to do there.
I was able to change the foreach loop to use this:
((info-gather.exe 2>&1)[1] | Out-String) -split "[`r`n]" | foreach-object
Since this does not write to a file, -WhatIf
no longer overrides it.
There is probably a simpler and cleaner way to do this (for instance, if there was a way to pipe stderr to Out-String
directly).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With