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?
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.
$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.
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.
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
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
}
}
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>>
}
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
)
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