Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to propagate -Verbose to module functions?

According to answers like this one and my own experience, Powershell can take care of propagating -Verbose (and -Debug) automatically, which is very convenient. However this stops working when the functions which I want to propagate verbosity to are in a module. Code used for testing this:

Create a directory called Mod somewhere, suppose in c:, and add 2 files:

File c:\Mod\Functions.ps1:

function Show-VerbosityB { [cmdletbinding()]Param()
  Write-Output "Show-VerbosityB called"
  Write-Verbose "Show-VerbosityB is Verbose"
}

File c:\Mod\Mod.psd1:

@{
ModuleVersion = '1.0.0.0'
NestedModules = @('Functions.ps1')
FunctionsToExport = @('*-*')
}

Now crate the main script, say c:\Foo.ps1:

Import-Module c:\Mod

function Show-VerbosityA { [cmdletbinding()]Param()
  Write-Output "Show-VerbosityA called"
  Write-Verbose "Show-VerbosityA is Verbose"
}

function Show-Verbosity { [cmdletbinding()]Param()
  Write-Output "Show-Verbosity called"
  Write-Verbose "Show-Verbosity is Verbose"
  Write-Output "Testing propagation"
  Show-VerbosityA
  Show-VerbosityB
}

Show-Verbosity -Verbose

Results in

PS> . C:\Foo.ps1
Show-Verbosity called
VERBOSE: Show-Verbosity is Verbose
Testing propagation
Show-VerbosityA called
VERBOSE: Show-VerbosityA is Verbose
Show-VerbosityB called

Why is the Write-Verbose in the module's function skipped, why does propagation not behave like it does for Show-VerbosityA? (If I just dot-source Functions.ps1 instead of importing the module, the line VERBOSE: Show-VerbosityB is Verbose is printed). I could make propagation manual by e.g. calling Show-VerbosityB -Verbose:$PSBoundParameters['Verbose']. Or are there other, preferrably shorter, ways? It is quite messy if functions behave differently depending on whether they are part of a module or dot-sourced.

like image 733
stijn Avatar asked Jul 04 '17 08:07

stijn


People also ask

How do I import a function from a module?

To make use of the functions in a module, you'll need to import the module with an import statement. An import statement is made up of the import keyword along with the name of the module. In a Python file, this will be declared at the top of the code, under any shebang lines or general comments.

What are module functions?

Functions provide the basic building blocks of functionality in larger programs (and computer simulations), and help to control the inherent complexity of the process. We can group functions together into a Python module (see modules), and in this way create our own libraries of functionality.

Can we import module in function?

Python modules can get access to code from another module by importing the file/function using import. The import statement is the most common way of invoking the import machinery, but it is not the only way.


1 Answers

The reason this is happening is because the $VerbosePreference is not propagated when the module is called. I modified your script to explicitly print the value at the same points you are outputting via Write-Verbose and Write-Output.

This powershell.org post proposes adding this to the module, which worked like a charm for me:

if (-not $PSBoundParameters.ContainsKey('Verbose'))
{
    $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference')
}

One of the comments mentions bug report with link (it doesn't exist or I don't have permissions to view)

The issue is discussed in a TechNet post, with a link to a Get-CallerPreferance function that addresses this issue.


Module:

function Show-VerbosityB { [cmdletbinding()]Param()

    <# uncomment to get verbose preference from caller, when verbose switch not explicitly used.
    if (-not $PSBoundParameters.ContainsKey('Verbose'))
    {
        $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference')
    }
    #>

    Write-Output "`nShow-VerbosityB called"
    Write-output "Global pref: $($global:VerbosePreference)"
    Write-output "Script pref: $($script:VerbosePreference)"
    Write-output "Effect pref: $VerbosePreference"
    Write-Verbose "Show-VerbosityB is Verbose"
}

Caller:

Import-Module C:\Mod

Write-output "On startup: $VerbosePreference"

function Show-VerbosityA { [cmdletbinding()]Param()
  Write-Output "`nShow-VerbosityA called"
  Write-output "Global pref: $($global:VerbosePreference)"
  Write-output "Script pref: $($script:VerbosePreference)"
  Write-output "Effect pref: $VerbosePreference"
  Write-Verbose "Show-VerbosityA is Verbose"
}

function Show-Verbosity { [cmdletbinding()]Param()
  Write-Output "`nShow-Verbosity called"
  Write-output "Global pref: $($global:VerbosePreference)"
  Write-output "Script pref: $($script:VerbosePreference)"
  Write-output "Effect pref: $VerbosePreference"
  Write-Verbose "Show-Verbosity is Verbose"
  Write-Output "`nTesting propagation"
  Show-VerbosityA
  Show-VerbosityB
}

Show-Verbosity -Verbose
like image 101
G42 Avatar answered Oct 06 '22 00:10

G42