Передача статуса -Verbose командлетам модуля
У меня есть модуль PowerShell, который инкапсулирует ряд часто используемых бизнес-функций. Обычно он не вызывается из консоли; скорее, его функции вызываются автоматическими сценариями развертывания и управления, которые импортируют модуль.
Модуль включает в себя функцию ведения журнала, которая выполняет запись в централизованное место ведения журнала. Я также хотел бы подключиться к функциональности Write-Verbose для записи на консоль.
#'Start Script.ps1
#'----------------
import-module Corporate
Write-Logger 'Foo'
Мое ограничение заключается в том, что - из модуля Corporate PowerShell - мне нужно определить, был ли вызван Script.ps1 с параметром -Verbose. В идеале я хотел бы, чтобы код определения целиком находился внутри самого модуля.
Вот пример:
[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
Сохраните выше как test.ps1. Когда вызывается из консоли:
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
Как видите, переменная $VerbosePreference недоступна из модуля. Есть ли способ узнать из модуля, был ли вызван вызывающий скрипт с флагом -Verbose.
4 ответа
Существует переменная с именем $VerbosePreference, которую вы можете проверить, чтобы увидеть, как должен обрабатываться подробный вывод. Однако здесь возникают проблемы: скрипты загружаются в отдельную область. Если вы читаете Get-Help about_scopes
, вот увидишь:
Автор сценария: Область, которая создается во время работы файла сценария. Только Команды в сценарии выполняются в области действия сценария. к команды в сценарии, область действия сценария является локальной объем.
Вместо этого вы можете добавить скрипт в текущую область, используя нотацию точечного источника. Из того же файла справки, под заголовком "Использование точечной нотации с областью действия" указано, что:
Сценарии и функции следуют всем правилам области видимости. Вы создаете их в определенной области, и они влияют только на эту область, если вы не используете командлет параметр или модификатор области, чтобы изменить эту область. Но вы можете добавить скрипт или функцию к текущей области, используя точку обозначение источника. Затем, когда скрипт выполняется в текущей области, любой доступны функции, псевдонимы и переменные, которые создает скрипт в текущем объеме.
Я предлагаю прочитать больше об областях в Get-Help about_scopes
справочная глава.
Для быстрой проверки того, работает ли это или нет:
[CmdletBinding ()] ПАРАМЕТР () New-Module -Name TempModule -ScriptBlock { функция Show-ModuleVerbosePreference { [CmdletBinding()] ПАРАМЕТР () Write-Host "Подробное предпочтение в функции модуля: $VerbosePreference" } } | Из-Null функция Show-ScriptVerbosePreference { [CmdletBinding()] ПАРАМЕТР () Write-Host "Подробное предпочтение в функции скрипта: $VerbosePreference" } Шоу-ScriptVerbosePreference Шоу-ModuleVerbosePreference
И если мы попытаемся вызвать этот файл сценария, используя разные методы, мы получим следующий вывод:
PS C: \>. \ Verbosity.ps1 Подробное предпочтение в функции скрипта: SilentlyContinue Подробное предпочтение в функции модуля: SilentlyContinue PS C:\> .\ Verbosity.ps1 -Verbose VERBOSE: Экспорт функции "Show-ModuleVerbosePreference". VERBOSE: функция импорта "Show-ModuleVerbosePreference". Подробное предпочтение в функции скрипта: Продолжить Подробное предпочтение в функции модуля: SilentlyContinue PS C:\> . .\ Verbosity.ps1 Подробное предпочтение в функции скрипта: SilentlyContinue Подробное предпочтение в функции модуля: SilentlyContinue PS C:\> . .\verbosity.ps1 -Verbose VERBOSE: Экспорт функции "Show-ModuleVerbosePreference". VERBOSE: функция импорта "Show-ModuleVerbosePreference". Подробное предпочтение в функции скрипта: Продолжить Подробное предпочтение в функции модуля: Продолжить
Поэтому, используя нотацию с точечным источником, мы добавили область действия скрипта в текущую область, что, кажется, делает настройку VerbosePreference видимой и в методе модуля.
Можно передать большинство общих параметров, используя соответствующие переменные предпочтения и синтаксис, подобный этому, -Parameter:$ParameterPreference
, Таким образом, для конкретного случая многословия, синтаксис -Verbose:$VerbosePreference
,
Есть несколько исключений:
- Отладка: значение
$DebugPreference
автоматически передается, но с указанием-Debug
переключить силы$DebugPreference
вInquire
, - WhatIf: автоматически передается.
Я изменил пример кода OP следующим образом:
[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
}
Сохраните выше как test.ps1. Когда вызывается из консоли:
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".
Кроме того, проход для $DebugPreference
, $WarningPreference
а также $ErrorActionPreference
также работает:
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
автоматически передается:
PS C:\temp> .\test.ps1 -FullPassThru -WhatIf
What if: Performing the operation "Remove Item" on target "Item: DEMONSTRATE_PASS_THRU".
Это также обрабатывает -WarningAction
а также -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
В моем.psm1 я помещаю команду, подобную этой:
If ((Get-PSCallStack) [1].Arguments -like '* Verbose = True *') {Write-Host 'Скриптом.ps1, импортирующим этот модуль, является Verbose'};
Вы можете использовать блок скрипта для установки переменной, например, $VerbosePreference в области видимости вашего модуля, или вашей собственной уникальной переменной для вашей собственной логики.
Попробуйте метод ContainsKey:
$PSCmdlet.MyInvocation.BoundParameters.ContainsKey('verbose')