MisterSeajay
MisterSeajay

Reputation: 4669

How can I suppress "What if" text being written to the console

I commonly use SupportsShouldProcess in my PowerShell functions along with $PSCmdlet.ShouldProcess() so I can sanity-check what a script is going to do. Generally I only implement this around actions that will change the environment, e.g. Add-, New-, Set- cmdlets, etc. In some cases I also want to bypass Get- cmdlets when running a script with the -WhatIf switch. For example:

I have a script that fingerprints all files in a folder using Get-FileHash before doing something to each file. In this example there are 10k+ files with an average size of 100MB or more and I don't want to spend time actually fingerprinting the files when I use -WhatIf. I cannot wrap the whole operation is just one $PSCmdlet.ShouldProcess("All Files","Get-FileHash") block.

The effect of running $PSCmdlet.ShouldProcess() for each item in a loop is that I dump thousands of lines of "What if:" text back to the console.

Question: Is there a way to use $PSCmdlet.ShouldProcess() so it does not write to the console? If not, what workarounds might people use?


Example code

While I think the question works just in an abstract sense, this is a pretty practical forum so here is a simple example of the task I referred to above:

$Files = Get-ChildItem -Path <ReallyBigFolder>

foreach($File in $Files){
  $Action = Get-MyAction -Filename -$File.Fullname

  # Take hash of file
  $Hash = Get-FileHash -Path -$File.Fullname

  # Keep audit happy
  Write-Audit -Action $Action -Hash $Hash

  switch($Action){
    "Retain" {
      # do nothing
      break
    }

    "Remove" {
      if($PSCmdlet.ShouldProcess($File.Fullname,"Remove-Item")){
        Remove-Item $File.Fullname
      }
      break
    }

    default { # barf }
  }
}

Assume that 95% of the files will be kept, so in this example we "only" get 500 lines of WhatIf output on the screen, but spend time hashing files and writing audit logs (assume the latter is calling a REST API or something else that is slow over multiple iterations).

If I put the Get-FileHash and Write-Audit cmdlets in a ShouldProcess() block then I save time but get 10k or more lines written to screen.

I'm sure this example (and indeed my real code) could be restructured to keep the output under control, or I can just ignore the verbosity of WhatIf, but it happens that today I wondered if I could suppress the output...

Upvotes: 5

Views: 1644

Answers (4)

pDale Campbell
pDale Campbell

Reputation: 1

I had a parallel situation, where I wanted to write to a log file even when -WhatIf was supplied.

You could record the state of -WhatIf, turn it off temporarily, manually control the action you want to perform, then restore the original state of -WhatIf:

$MyWhatIf= $WhatIfPreference
$WhatIfPreference= $False
If (! $MyWhatIf) { Do-YourThing }
$WhatIfPreference= $MyWhatIf

Upvotes: 0

MisterSeajay
MisterSeajay

Reputation: 4669

As an extension to the answer from @martin-brandl, here is how you might check for implicit use of the WhatIf switch:

if(((Get-PSCallStack).InvocationInfo.BoundParameters.ContainsKey("WhatIf")) `
    -and ((Get-PSCallStack).InvocationInfo.BoundParameters.WhatIf -eq $true))
{
  # don't do whatever you might have done
}

That is: check the call stack to see whether -WhatIf was supplied as a parameter anywhere, and verify that someone didn't negate it with -WhatIf:$false.

Maybe the comment on Martin's answer from @briantist about using $WhatIfPreference is easier though!

Upvotes: 2

briantist
briantist

Reputation: 47832

The way I'm interpreting your question, it seems like you're not quite implementing -WhatIf correctly in this instance. -WhatIf should ensure nothing is changed. If you want to just to skip the fingerprinting but still do something to each file then you should implement your own switch like -NoFingerprint and use the value of that.

You should continue implementing -WhatIf, which will not process the files at all (in which case it may make sense to keep outputting all the lines).

Upvotes: 0

Martin Brandl
Martin Brandl

Reputation: 58981

I doubt you can supress the ShouldProcess output. As a workaround, you can check whether the -whatif parameter is present in the $PSBoundParameters:

if ($PSBoundParameters.ContainsKey('WhatIf'))
{
   # do something here without
}

Upvotes: 4

Related Questions