question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Give advanced PowerShell functions and scripts an opt-in to limit verbose output to explicit Write-Verbose calls

See original GitHub issue

Follow-up from #13636:

Note:

  • Substantially revised after the discussion below.

  • While the verbose stream is being discussed, the same applies analogously to the warning, debug, and information streams.

Summary of the new feature/enhancement

As a script/function author, I want to be able to create advanced functions / scripts that are cmdlet-like and deliberately limit verbose output to explicit Write-Verbose calls only (by default).

Because of PowerShell’s dynamic scoping, the stream-controlling $*Preference variables are visible to all child scopes of a given script/function and also apply to cmdlet calls inside them. This also applies to the stream-controlling common parameters (e.g., -Verbose), which PowerShell automatically translates into function/script-local $*Preference variables.

While this can be helpful in troubleshooting a function or script, it can also lead to a flood of unwanted verbose output that drowns out the verbose output of interest. (A related problem are the verbose messages that can surface due to auto-loading of the module containing the command being invoked - see #13657.)

For instance, in the following (simulated) advanced function, I may want to show the user the explicit Write-Verbose call’s output only, not also the verbose messages produced by the Import-Module call, and the (simulated) call to another script or function.

# The script block represents an *advanced function*.
& {
  [CmdletBinding()]
  param()

  # This also produces verbose output.
  Import-Module PSReadLine

  # Simulate a call to other PowerShell functions / scripts:
  # This also produces verbose output.
  & {
    Write-Verbose 'in child scope'
  }

  # The only explicit Write-Verbose call
  Write-Verbose Done.

} -Verbose

For carefully crafted, cmdlet-like advanced scripts/functions, it would be helpful to have an opt-in mechanism that makes PowerShell limit verbose output to explicit Write-Verbose calls only (by default), so that the verbose output isn’t “polluted” by verbose output from internal calls that should be considered implementation details.

While there are workarounds, they are cumbersome; here’s one, which demonstrates the desired behavior:

& {
  [CmdletBinding()]
  param()

  # If verbose output is turned on, hide the setting from the descendant scopes,
  # but make all Write-Verbose calls *in this scope only* emit verbose output.
  if ($VerbosePreference -eq 'Continue') {
    $VerbosePreference = 'SilentlyContinue' # Hide from cmdlet calls and descendant scopes.
    # Apply only to Write-Verbose calls in the current scope.
    $private:PSDefaultParameterValues = $PSDefaultParameterValues ? $PSDefaultParameterValues.Clone() : [System.Management.Automation.DefaultParameterDictionary]::new()
    $private:PSDefaultParameterValues['Write-Verbose:Verbose'] = $true
  }

  # This is now quiet.
  Import-Module PSReadLine

  # Simulate a call to other PowerShell functions / scripts:
  # This is now quiet too.
  & {
    Write-Verbose 'in child scope'
  }

  # Only this will print.
  Write-Verbose Done.

} -Verbose

Proposed technical implementation details (optional)

Implement a new StreamPreferencePropagation property on the CmdletBinding attribute, which defaults to $true and can be set to $false (analogous to the PositionalBinding property):

& {
  # Note the new property.
  [CmdletBinding(StreamPreferencePropagation = $false)]
  param()

  # This is now quiet.
  Import-Module PSReadLine

  # Simulate a call to other PowerShell functions / scripts:
  # This is now quiet too.
  & {
    Write-Verbose 'in child scope'
  }

  # Only this will print.
  Write-Verbose Done.

} -Verbose

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
jhoneillcommented, Sep 21, 2020

I think this will annoy roughly as many people as it pleases. There are functions which have no write-verbose statements which are wrappers for another command which we want the detail from (IIRC I did this a lot to find what went into invoke-restmethod in other functions). I’ve also written functions where I expressly called other things with -verbose:$false because I did write to verbose in the function, and tens or hundreds of function calls with verbose made it hard to see the wood for the trees.

I’m not sure which is the more common case, but my gut says its not 10 or 20 of one to one of the other.

1reaction
mklement0commented, Sep 26, 2020

@jazzdelightsme

something like a still-dynamically-scoped-but-stops-at-module-boundaries concept

It actually does stop a module boundaries, but that is in itself highly problematic: #4568

Does my strategy for (1) not cover some scenario?

Yes, it’s an effective approach (which @jhoneill also mentioned), but my concern was that it is cumbersome and easy to forget.

But the point about intra-module helper code is a valid one.

I’m closing this, and let’s hope that fixing #13657 alone will go a long way toward mitigating the problem.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Use PowerShell to Write Verbose Output - Scripting Blog
By default, Windows PowerShell is set up to use Write-Verbose. The issue is that out of the box, verbose messages do not display....
Read more >
PowerShell Advanced Functions | ScriptRunner
PowerShell advanced functions provide the capability to extend a simple PowerShell script to a tool which behaves like a native PowerShell ...
Read more >
Write Advanced functions in PowerShell using various Write ...
We will be specifically discussing about below cmdlets: Write-Host; Write-Output; Write-Debug; Write-Warning; Write-Error; Write-Verbose; Write- ...
Read more >
Fun With PowerShell Write-Verbose
In this post we saw how the built in -Verbose switch works along with the companion Write-Verbose . This can provide a useful...
Read more >
Powershell script support for -verbose
I'm creating a .ps1 script which invokes Write-Verbose . I would like to be able to enable/disable these. I was hoping that I...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found