2010-11-29 2 views
33

По умолчанию любая именованная функция, имеющая атрибут [CmdletBinding()], принимает параметры -debug и -verbose (и несколько других) и имеет предопределенные $ debug и $ verbose. Я пытаюсь понять, как передать их другим командлетам, которые вызываются внутри функции.Как правильно использовать параметры -verbose и -debug в пользовательском командлете

Скажем, у меня есть Командлет вроде этого:

function DoStuff() { 
    [CmdletBinding()] 

    PROCESS { 
     new-item Test -type Directory 
    } 
} 

если -debug или -verbose был принят в моей функции, я хочу передать этот флаг в new-item командлета. Какая правильная схема для этого?

+0

PowerShell уже делает это за вас. Не так прямо, как вы могли бы ожидать. См. Мой ответ ниже – 2013-12-29 22:30:43

ответ

25

Возможно, это звучит странно, но для командлета нет простого способа узнать его подробный или отладочный режим. Взгляните на связанный с этим вопрос:

How does a cmdlet know when it really should call WriteVerbose()?

Не совершенным, но практически разумным вариантом является введение собственных параметров командлета (например $MyVerbose, $MyDebug) и использовать их в коде явно.

function DoStuff { 
    [CmdletBinding()] 
    param 
    (
     # unfortunately, we cannot use Verbose name with CmdletBinding 
     [switch]$MyVerbose 
    ) 

    process { 

     if ($MyVerbose) { 
      # do verbose stuff 
     } 

     # pass $MyVerbose in the cmdlet explicitly 
     New-Item Test -Type Directory -Verbose:$MyVerbose 
    } 
} 

DoStuff -MyVerbose 

UPDATE

Когда нам нужно только переключатель (не, скажем, значение уровня детальности), то подход с $PSBoundParameters, пожалуй, лучше, чем предложенная выше дополнительных параметров:

function DoStuff { 
    [CmdletBinding()] 
    param() 

    process { 
     if ($PSBoundParameters['Verbose']) { 
      # do verbose stuff 
     } 

     New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true) 
    } 
} 

DoStuff -Verbose 

В любом случае, это не так. Если будут лучшие решения, я бы очень хотел их узнать.

+0

Я думаю, что второй пример может оценивать Verbose в true, если он не был явно установлен false при вызове функции. Кажется, что это верно, когда задано значение null. – craika 2010-11-29 12:20:27

+0

@Alisdair Craik: хорошо поймать, спасибо, я исправил это (и протестировал это время). Странно, не так ли? Примечание: в вашем ответе есть, возможно, и незначительный недостаток: проверить `ContainsKey()` недостаточно, потому что фактическое значение этого существующего ключа может быть еще `$ false`. Это редкий случай, но это невозможно. – 2010-11-29 12:51:20

+2

Это трюк «-Vebose: (xxx)« Я не знал, что вы можете установить переключатель таким образом. Я думал, что это всегда включать или исключать. Я не знал, что вы можете прямо установить значение этого переключателя. – Micah 2010-11-29 13:07:39

2

Вы можете создать новую таблицу хэша на основе связанных параметров debug или verbose, а затем поместить ее во внутреннюю команду. Если вы просто указать переключатели (и не передавая ложный переключатель, как $ отлаживать: $ лжи), вы можете просто проверить существование отладки или многословная:

function DoStuff() { 
    [CmdletBinding()] 

    PROCESS { 
     [email protected]{Verbose=$PSBoundParameters.ContainsKey'Verbose');Debug=$PSBoundParameters.ContainsKey('Debug')} 
     new-item Test -type Directory @HT 
    } 
} 

Если вы хотите, чтобы передать параметр значение это более сложный, но может быть сделано с:

function DoStuff { 
    [CmdletBinding()] 
    param() 
    PROCESS { 
    $v,$d = $null 
    if(!$PSBoundParameters.TryGetValue('Verbose',[ref]$v)){$v=$false} 
    if(!$PSBoundParameters.TryGetValue('Debug',[ref]$d)){$d=$false} 
    [email protected]{Verbose=$v;Debug=$d} 
    new-item Test -type Directory @HT 
    } 
} 
32

$PSBoundParameters не то, что вы ищете. Использование атрибута [CmdletBinding()] позволяет использовать в вашем скрипте $PSCmdlet, а также предоставить флаг Verbose. На самом деле это то же самое, что вы должны использовать.

С помощью [CmdletBinding()] вы можете получить доступ к связанным параметрам через $PSCmdlet.MyInvocation.BoundParameters. Вот функция, которая использует CmdletBinding и просто сразу вводит вложенное приглашение для проверки переменных, доступных внутри области функций.

PS D:\> function hi { [CmdletBinding()]param([string] $Salutation) $host.EnterNestedPrompt() }; hi -Salutation Yo -Verbose 

PS D:\>>> $PSBoundParameters 

____________________________________________________________________________________________________ 
PS D:\>>> $PSCmdlet.MyInvocation.BoundParameters 

Key Value                                                   
--- -----                                                   
Salutation Yo                                                    
Verbose True                      

Таким образом, в вашем примере, вы хотели бы следующее:

function DoStuff ` 
{ 
    [CmdletBinding()] 
    param() 
    process 
    { 
     new-item Test -type Directory ` 
     -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) 
    } 
} 

Это охватывает -Verbose, -Verbose: $ ложный, -Verbose: $ верно, и тот случай, когда переключатель вообще отсутствует.

3

С риском возрождения и старой резьбы. Вот мое решение.

function DoStuff { 
    [CmdletBinding()] 
    param() 

    BEGIN 
    { 
    [email protected]{ 
     Verbose=If ($PSBoundParameters.Verbose -eq $true) { $true } else { $false }; 
     Debug=If ($PSBoundParameters.Debug -eq $true) { $true } else { $false } 
    } 
    } # BEGIN ENDS 

    PROCESS 
    { 
    New-Item Example -ItemType Directory @CMDOUT 
    } # PROCESS ENDS 

    END 
    { 
    } #END ENDS 
} 

Что это делает отличается от других примеров является то, что он будет repsect «-Verbose: $ лжи» или «-Debug: $ лжи». Он будет установлен только -Verbose/-Debug до $ верно, если вы используете следующие:

DoStuff -Verbose 
DoStuff -Verbose:$true 
DoStuff -Debug 
DoStuff -Debug:$true 
0

Я думаю, что это самый простой способ:

Function Test { 
    [CmdletBinding()] 
    Param (
     [parameter(Mandatory=$False)] 
     [String]$Message 
    ) 

    Write-Host "This is INFO message" 

    if ($PSBoundParameters.debug) { 
     Write-Host -fore cyan "This is DEBUG message" 
    } 

    if ($PSBoundParameters.verbose) { 
     Write-Host -fore green "This is VERBOSE message" 
    } 

    "" 
} 
Test -Verbose -Debug 
22

Там нет необходимости. PowerShell уже делает это, как показывает приведенный ниже код.

function f { [cmdletbinding()]Param()  
    "f is called" 
    Write-Debug Debug 
    Write-Verbose Verbose 
} 
function g { [cmdletbinding()]Param() 
    "g is called" 
    f 
} 
g -Debug -Verbose 

Выход

g is called 
f is called 
DEBUG: Debug 
VERBOSE: Verbose 

Это не сделано, как прямой, как прохождение -Debug к следующему командлету хотя. Это делается через переменные $ DebugPreference и $ VerbrosePreference. Write-Debug и Write-Verbose действуют так, как вы ожидали, но если вы хотите сделать что-то другое с помощью отладки или подробного описания, вы можете прочитать here, как проверить себя.

2

Лучший способ сделать это, установив $VerbosePreference. Это позволит использовать подробный уровень для всего скрипта. Не забудьте отключить его до конца скрипта.

Function test 
{ 
    [CmdletBinding()] 
    param($param1) 


    if($psBoundParameters['verbose']) 
    { 
    $VerbosePreference = "Continue" 
    Write-verbose " Verbose mode is on" 
    } 
    else 
    { 
    $VerbosePreference = "SilentlyContinue" 
    Write-verbose " Verbose mode is Off" 
    } 
    <<your code>> 
    } 
1

Вы можете установить VerbosePreference как глобальную переменную на запуске вашего сценария, а затем проверить для глобальной переменной в пользовательском командлете.

Сценарий:

$global:VerbosePreference = $VerbosePreference 
Your-CmdLet 

Ваших командлеты:

if ($global:VerbosePreference -eq 'Continue') { 
    # verbose code 
} 

Проверка явно для «Продолжить» позволяет сценарий равного -verbose:$false при вызове Командлета из сценария, который не установите глобальную переменную (в этом случае это $null)

 Смежные вопросы

  • Нет связанных вопросов^_^