I have a PowerShell module that encapsulates a number of commonly-used business functions. It's not generally called from the console; rather, its functions are called by automated deployment and management scripts that import the module.
The module incorporates a logging function that writes to both a centralised logging location. I'd also like to hook into the Write-Verbose functionality to write to the console as well.
#'Start Script.ps1
#'----------------
Import-Module Corporate
Write-Logger 'Foo'
My restriction is that - from within the Corporate PowerShell module - I need to determine whether Script.ps1 has been called with the -Verbose
parameter. Ideally, I would like the determination code entirely within the module itself.
Here's an example:
[CmdletBinding()]
Param ()
New-Module -Name TempModule -ScriptBlock {
function Test-ModuleVerbose() {
[CmdletBinding()]
Param ()
PROCESS {
$vb = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true)
Write-Host ("1: Module verbose preference: " + ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true))
Write-Host ("2: Module verbose preference: " + $Script:VerbosePreference)
Write-Host ("3: Module verbose preference: " + $VerbosePreference)
}
}
} | Out-Null
function Test-Verbose() {
[CmdletBinding()]
Param ()
PROCESS {
Write-Host ("Verbose preference: $VerbosePreference")
Test-ModuleVerbose
}
}
Test-Verbose
Save the above as test.ps1. When invoked from the console:
PS C:\temp> .\test.ps1
Verbose preference: SilentlyContinue
1: Module verbose preference: False
2: Module verbose preference:
3: Module verbose preference: SilentlyContinue
PS C:\temp> .\test.ps1 -Verbose
VERBOSE: Exporting function 'Test-ModuleVerbose'.
VERBOSE: Importing function 'Test-ModuleVerbose'.
Verbose preference: Continue
1: Module verbose preference: False
2: Module verbose preference:
3: Module verbose preference: SilentlyContinue
As you can see, the $VerbosePreference variable is not available from within the module. Is there a way of picking up from within the module whether the calling script has been invoked with the -Verbose
flag?
It is possible to pass-through most of the common parameters using the matching preference variables and a syntax like this, -Parameter:$ParameterPreference
. So, for the specific case of verbose, the syntax is -Verbose:$VerbosePreference
.
There are a couple of exceptions:
$DebugPreference
is automatically passed-through, but specifying the -Debug
switch forces $DebugPreference
to Inquire
.I have modified the OP code sample as follows:
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Switch]$FullPassThru
)
New-Module -Name TempModule -ScriptBlock {
function Test-ModuleVerbose
{
[CmdletBinding(SupportsShouldProcess=$true)]
param ()
Write-Host "1: Module: verbose parameter is bound : $($PSCmdlet.MyInvocation.BoundParameters['Verbose'])"
Write-Host "2: Module: verbose preference : $VerbosePreference"
# Write-Verbose will just work without any change
Write-Verbose "Verbose"
# Other commands need the $VerbosePreference passed in
Set-Item -Path Env:\DEMONSTRATE_PASS_THRU `
-Value 'You can safely delete this variable' `
-Verbose:$VerbosePreference
}
function Test-ModulePreferencePassThru
{
[CmdletBinding(SupportsShouldProcess=$true)]
param()
Write-Debug "DebugPreference: $DebugPreference"
Write-Warning "WarningPreference: $WarningPreference"
Write-Error "ErrorActionPreference: $ErrorActionPreference"
Set-Item -Path Env:\DEMONSTRATE_PASS_THRU `
-Value 'You can safely delete this variable' `
-Verbose:$VerbosePreference `
-WarningAction:$WarningPreference `
-ErrorAction:$ErrorActionPreference
}
} | Out-Null
function Test-Verbose
{
[CmdletBinding(SupportsShouldProcess=$true)]
param()
Write-Host ("Verbose preference: $VerbosePreference")
Test-ModuleVerbose -Verbose:$VerbosePreference
}
function Test-PreferencePassThru
{
[CmdletBinding(SupportsShouldProcess=$true)]
param()
Test-ModulePreferencePassThru -Verbose:$VerbosePreference
}
try
{
if ($FullPassThru -eq $false)
{
# just demonstrate -verbose pass-through
Test-Verbose
}
else
{
# most of the preferences can be explicitly passed-through, however:
#
# -Debug : $DebugPreference is automatically passed-through
# and -Debug forces $DebugPreference to 'Inquire'
# -WhatIf : automatically passed-through
Test-ModulePreferencePassThru -Verbose:$VerbosePreference `
-WarningAction:$WarningPreference `
-ErrorAction:$ErrorActionPreference | Out-Null
}
}
finally
{
# cleanup
Remove-Item -Path Env:\DEMONSTRATE_PASS_THRU -Force | Out-Null
}
Save the above as test.ps1. When invoked from the console:
PS C:\temp> .\test.ps1
Verbose preference: SilentlyContinue
1: Module: verbose parameter is bound : False
2: Module: verbose preference : SilentlyContinue
PS C:\temp> .\test.ps1 -Verbose
VERBOSE: Exporting function 'Test-ModuleVerbose'.
VERBOSE: Exporting function 'Test-ModulePreferencePassThru'.
VERBOSE: Importing function 'Test-ModulePreferencePassThru'.
VERBOSE: Importing function 'Test-ModuleVerbose'.
Verbose preference: Continue
1: Module: verbose parameter is bound : True
2: Module: verbose preference : Continue
VERBOSE: Verbose
VERBOSE: Performing the operation "Set Item" on target "Item: DEMONSTRATE_PASS_THRU Value: You can safely delete this variable".
Furthermore, pass-through for $DebugPreference
, $WarningPreference
and $ErrorActionPreference
also works:
PS C:\temp> $VerbosePreference = 'Continue'
PS C:\temp> $DebugPreference = 'Continue'
PS C:\temp> $WarningPreference = 'Continue'
PS C:\temp> $ErrorActionPreference = 'Continue'
PS C:\temp> .\test.ps1 -FullPassThru
VERBOSE: Exporting function 'Test-ModuleVerbose'.
VERBOSE: Exporting function 'Test-ModulePreferencePassThru'.
VERBOSE: Importing function 'Test-ModulePreferencePassThru'.
VERBOSE: Importing function 'Test-ModuleVerbose'.
DEBUG: DebugPreference: Continue
WARNING: WarningPreference: Continue
Test-ModulePreferencePassThru : ErrorActionPreference: Continue
At C:\OAASMain\Online\ContainerService\Tools\docker\test.ps1:72 char:9
+ Test-ModulePreferencePassThru -Verbose:$VerbosePreference `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-ModulePreferencePassThru
VERBOSE: Performing the operation "Set Item" on target "Item: DEMONSTRATE_PASS_THRU Value: You can safely delete this variable".
-WhatIf
is automatically passed-through:
PS C:\temp> .\test.ps1 -FullPassThru -WhatIf
What if: Performing the operation "Remove Item" on target "Item: DEMONSTRATE_PASS_THRU".
This also handles -WarningAction
and -ErrorAction
:
PS C:\temp> .\test.ps1 -FullPassThru -WarningAction Ignore -ErrorAction Stop
Test-ModulePreferencePassThru : ErrorActionPreference : Stop
At C:\OAASMain\Online\ContainerService\Tools\docker\test.ps1:72 char:9
+ Test-ModulePreferencePassThru -Verbose:$VerbosePreference `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-ModulePreferencePassThru