Par défaut, toute fonction nommée ayant l'attribut [CmdletBinding ()] accepte les paramètres -debug et -verbose (et quelques autres) et comporte des variables prédéfinies $ debug et $ verbose. Ce que j'essaie de comprendre, c'est comment les transmettre à d'autres applets de commande qui sont appelées dans la fonction.
Disons que j'ai une applet de commande comme ceci:
function DoStuff() {
[CmdletBinding()]
PROCESS {
new-item Test -type Directory
}
}
si -debug
ou -verbose
a été passé dans ma fonction, je souhaite passer cet indicateur dans la cmdlet new-item
. Quel est le bon modèle pour faire cela?
Cela peut sembler étrange, mais il n’existe pas de moyen facile pour une applet de commande de connaître son mode verbose ou de débogage. Jetez un oeil à la question connexe:
Comment une applet de commande sait-elle à quel moment elle doit appeler WriteVerbose ()?
Une option non parfaite mais pratiquement raisonnable consiste à introduire vos propres paramètres d'applet de commande (par exemple, $MyVerbose
, $MyDebug
) et à 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
METTRE À JOUR
Lorsque nous n'avons besoin que d'un commutateur (pas, par exemple, de valeur de niveau de verbosité), l'approche avec $PSBoundParameters
est peut-être préférable aux paramètres supplémentaires proposés ci-dessus:
function DoStuff {
[CmdletBinding()]
param()
process {
if ($PSBoundParameters['Verbose']) {
# do verbose stuff
}
New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)
}
}
DoStuff -Verbose
Ce n'est pas parfait de toute façon. S'il existe de meilleures solutions, j'aimerais vraiment les connaître moi-même.
$PSBoundParameters
n'est pas ce que vous cherchez. L'utilisation de l'attribut [CmdletBinding()]
permet d'utiliser $PSCmdlet
dans votre script, en plus de fournir un indicateur Verbose. C'est en fait ce même Verbose que vous êtes censé utiliser.
Grâce à [CmdletBinding()]
, vous pouvez accéder aux paramètres liés via $PSCmdlet.MyInvocation.BoundParameters
. Voici une fonction qui utilise CmdletBinding et entre simplement une invite imbriquée immédiatement pour examiner les variables disponibles dans 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 voudriez 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ù le commutateur 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
Cela ne se fait pas aussi directement que de passer -Debug à la cmdlet suivante. Cela se fait via les variables $ DebugPreference et $ VerbrosePreference. Write-Debug et Write-Verbose agissent comme vous le souhaitez, mais si vous voulez faire quelque chose de différent avec debug ou verbose, vous pouvez lire ici comment vérifier par vous-même.
Avec un risque de renaissance et de vieux fils. 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 qui diffère des autres exemples est qu’il va représenter "-Verbose: $ false" ou "-Debug: $ false". Il ne définira -Verbose/-Debug sur $ true que si vous utilisez les éléments suivants:
DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true
La meilleure façon de le faire est de définir le $VerbosePreference
. Cela activera le niveau de commentaires pour l’ensemble du script. N'oubliez pas de le désactiver avant 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 créer une nouvelle table de hachage basée sur les paramètres liés de débogage ou détaillé, puis la scinder à la commande interne. Si vous ne spécifiez que des commutateurs (et ne passez pas un commutateur faux, comme $ debug: $ false), vous pouvez simplement vérifier l'existence de débogage ou de commentaires:
function DoStuff() {
[CmdletBinding()]
PROCESS {
$HT=@{Verbose=$PSBoundParameters.ContainsKey'Verbose');Debug=$PSBoundParameters.ContainsKey('Debug')}
new-item Test -type Directory @HT
}
}
Si vous voulez passer la valeur du paramètre, c'est plus compliqué, mais vous pouvez le faire 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
}
}
Vous pouvez définir VerbosePreference en tant que variable globale au démarrage de votre script, puis rechercher la variable globale dans votre cmdlet personnalisée.
Scénario:
$global:VerbosePreference = $VerbosePreference
Your-CmdLet
Votre-CmdLet:
if ($global:VerbosePreference -eq 'Continue') {
# verbose code
}
La recherche explicite de 'Continuer' permet au script d'être égal à -verbose:$false
lorsque vous appelez le CmdLet à partir d'un script qui ne définit pas la variable globale (auquel cas c'est $null
)
Je pense que c'est le moyen le plus simple:
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