Comment utiliser correctement les paramètres-verbose et-debug dans le cmdlet personnalisé

par défaut, toute fonction nommée qui a l'attribut [CmdletBinding()] accepte les paramètres-debug et-verbose (et quelques autres) et a prédéfini les variables $debug et $verbose. Ce que j'essaie de comprendre c'est comment les transmettre à d'autres cmdlet qui sont appelés dans la fonction.

disons que j'ai un cmdlet comme celui-ci:

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory 
   }
}

si -debug ou -verbose était passé dans ma fonction je veux passer que signalez dans le cmdlet new-item . Quel est le bon modèle pour faire cela?

35
demandé sur inwenis 2010-11-29 10:06:15

8 réponses

cela peut sembler étrange, mais il n'est pas facile pour un cmdlet de connaître son mode verbose ou debug. Jetez un oeil à la question connexe:

comment un cmdlet sait-il quand il doit vraiment appeler WriteVerbose()?

une option non parfaite mais pratiquement raisonnable est d'introduire vos propres paramètres cmdlet (par exemple $MyVerbose , $MyDebug ) et de les utiliser explicitement dans le code.

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 

mise à JOUR

lorsque nous n'avons besoin que d'un commutateur (pas, disons, de la valeur du niveau de verbosité) alors l'approche avec $PSBoundParameters est peut-être meilleure que proposée ci-dessus paramètres supplémentaires:

function DoStuff {
    [CmdletBinding()]
    param()

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

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

DoStuff -Verbose

tout n'est pas parfait de toute façon. S'il y a de meilleures solutions, j'aimerais les connaître moi-même.

28
répondu Roman Kuzmin 2017-05-23 12:03:09

$PSBoundParameters n'est pas ce que vous cherchez. L'utilisation de la [CmdletBinding()] attribut permet l'utilisation de $PSCmdlet dans votre script, en plus de fournir une Verbose drapeau. C'est en fait le même verbeux que vous êtes censé utiliser.

par [CmdletBinding()] , vous pouvez accéder aux paramètres liés par $PSCmdlet.MyInvocation.BoundParameters . Voici une fonction qui utilise CmdletBinding et entre simplement une invite imbriquée immédiatement afin d'examiner les variables disponibles à l'intérieur de la portée de la fonction.

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                                                                                       

donc dans votre exemple, vous voulez ce qui suit:

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

cela couvre-Verbose, -Verbose:$false, - Verbose:$true, et le cas où l'interrupteur n'est pas présent du tout.

33
répondu bwerks 2014-03-30 20:54:40

il n'y a pas besoin. PowerShell le fait déjà comme le prouve le code ci-dessous.

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

la sortie est

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

ce N'est pas aussi direct que passer-Debug au prochain cmdlet cependant. Cela se fait à travers les variables $DebugPreference et $VerbrosePreference. Écrire-Debug et écrire-Verbose agir comme vous l'attendez, mais si vous voulez faire quelque chose de différent avec debug ou verbose, vous pouvez lire ici comment pour le vérifier vous-même.

23
répondu Lars Truijens 2017-05-23 11:33:16

avec un risque de revivre et vieux fil. Voici ma solution.

function DoStuff {
    [CmdletBinding()]
    param ()

    BEGIN
    {
    $CMDOUT=@{
        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
}

ce que cela fait de différent des autres exemples est qu'il va représenter "-Verbose:$false" ou "-Debug:$false". Il ne définira-Verbose / - Debug à $ true que si vous utilisez ce qui suit:

DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true
5
répondu desek 2013-04-30 10:22:18

vous pouvez construire une nouvelle table de hachage basée sur les paramètres de débogage liés ou verbeux et ensuite la projeter à la commande interne. Si vous spécifiez des commutateurs (et ne passez pas un faux commutateur, comme $ debug: $ false), Vous pouvez simplement vérifier l'existence de debug ou verbose:

function DoStuff() { 
   [CmdletBinding()] 

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

Si vous souhaitez passer la valeur du paramètre, c'est plus compliqué, mais peut être fait avec:

function DoStuff {  
   [CmdletBinding()]  
   param()
   PROCESS {  
   $v,$d = $null
   if(!$PSBoundParameters.TryGetValue('Verbose',[ref]$v)){$v=$false}
   if(!$PSBoundParameters.TryGetValue('Debug',[ref]$d)){$d=$false}
   $HT=@{Verbose=$v;Debug=$d} 
   new-item Test -type Directory @HT 
   }  
}  
2
répondu craika 2010-11-29 13:14:32

la meilleure façon de le faire est de paramétrer le $VerbosePreference . Cela activera le niveau verbeux pour l'ensemble du script. Ne pas oublier de le désactiver à la fin du script.

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>>
   }
2
répondu MilindK 2014-09-18 08:52:06

vous pouvez définir la VerbosePreference comme une variable globale au démarrage de votre script et ensuite vérifier la variable globale dans votre cmdlet personnalisé.

Script:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

Votre-CmdLet:

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

la vérification explicite pour 'continuer' permet au script d'être égal à -verbose:$false quand vous appelez le CmdLet à partir d'un script qui ne définit pas la variable globale (dans ce cas, c'est $null )

1
répondu svandragt 2015-08-27 10:00:48

je pense que c'est la façon la plus facile:

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
0
répondu emekm 2013-09-09 11:38:07