Question [Astuce]Analyse des paramètres d'un script/fnction

Plus d'informations
il y a 17 ans 3 mois #3464 par Laurent Dardenne
Une correction de la version spécifique à PowerShell v1.
L'opérateur cast à un comportement différent des langages de POO tels que Delphi,C#,java,etc.
Si l'opération de cast échoue elle ne renvoi pas $null mais convertie l'objet en une string via un appel à la méthode ToSring().

[code:1]
function ValidateParameter([string]$Name,$Parameter,[Type] $Type, [Switch] $Strict)
{ # Renvoi $False si le contenu est à $Null.

# Si la validation demandée est stricte et que le type du paramètre est du type attendu , on renvoie $True
# Si la validation demandée est stricte et que le type du paramètre n'est pas du type attendu -> Exception

# Si la validation demandée n'est pas stricte, que le type du paramètre est du type attendu et
# que le cast réussi, on renvoi $True
# Si la validation demandée n'est pas stricte, que le type du paramètre n'est pas du type attendu et
# que le cast échoue -> Exception (note : avec le type [string] dans ce cas le cast réussi toujours)
#
#
# Exception : ArgumentTransformationMetadataException

Write-Debug \"ValidateParameter\"
Write-debug \"$Name\"
if ($Parameter -ne $null)
{Write-debug \"$($Parameter.GetType())\"}
else
{
Write-debug \"`Le paramètre $Name est à `$null.\"
return $False
}
Write-debug \"$Parameter\"
Write-debug \"$Type\"

#$host.EnterNestedPrompt()

#Le paramètre reçu est-il du type attendu ?
$isSameType=$Parameter -is $Type

#Peut-on caster la valeur reçue dans le type attendu ?
#En cas de cast impossible, l'opérateur -as appel la méthode ToString()
#Ce qui reste cohérent avec le parsing de PowerShell.
#Si le paramétre attendu est de type [string], dans ce cas une date sera transformée en string.
#Le cast du paramètre en un type [string] réussira toujours !
$isCastFail=($Parameter -as $Type) -eq $null

Write-debug \"$isNotSameType : $isNotSameType\"
Write-debug \"isCastFail : $isCastFail\"

#Si le cast demandé est strict, le type du paramètre doit être celui du type attendu
#ou
#si le cast demandé n'est pas strict que le type du paramètre n'est pas celui du type attendu et que le cast échoue.
if ( ($Strict.IsPresent -and !$isSameType) -or (!$Strict.IsPresent -and !$isSameType -and $isCastFail) )
{ #récupére le contexte d'appel de l'appelant
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
throw (new-object System.Management.Automation.ArgumentTransformationMetadataException \"$($Invocation.MyCommand).$($MyInvocation.MyCommand) : Impossible de convertir la valeur du paramètre $name « $($Parameter.GetType()) » en type « $($Type.ToString()) ».\"«»)
}
return $True
} #ValidateParameter
[/code:1]
test :
[code:1]
Function SendMail( $attach)
{
if (ValidateParameter \"attach\" $attach String)
{
if ( $Attach -eq [string]::Empty) {Throw \"Le contenu du paramètre Attach n'est pas renseigné.\"}
if (! (Test-path $Attach)) {Throw \"Le fichier n'existe pas : $Attach\"}
$Attach
\"Send mail\"
}
else {Throw \"La valeur du paramètre Attach est`$null ou n'est pas du type String.\"}
}

Sendmail
Sendmail \"\"
Sendmail \"C:\notExist.txt\"
# PS cast une date en une string
Sendmail get-date
Sendmail (get-date)
Sendmail 1..5

# PS cast un tableau en une string
Sendmail @(1..5)
Sendmail (Dir c:\)
[/code:1]
L'usage du switche Strict force la validation sur le type attendu et seulement celui-ci
[code:1]
if (ValidateParameter \"attach\" $attach String -Strict)
[/code:1]
Dans ce cas, à la différence de l'appel précédent, celui-ci échouera :
[code:1]
# Pas de PS cast,
#on attend un objet de type string et pas autre chose
Sendmail (get-date)[/code:1]
Tout compte fait je sens que j'ai un faible pour la version 2 de PowerShell :lol:<br><br>Message édité par: Laurent Dardenne, à: 17/12/08 15:16

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 1 mois #3873 par Laurent Dardenne
Une version modifiée :
[code:1]
function Test-Variable([System.Management.Automation.PSVariable] $Variable=$(Throw \&quot;Test-Variable : le paramètre Variable, de type PSVariable, doit être renseigné.\&quot;«»),
[Type] $Type=$(Throw \&quot;Test-Variable : le paramètre Type doit être renseigné.\&quot;«»),
[Switch] $Strict,
[Switch] $TestEmptyString)
{ # Léve une exception si le contenu de $Variable est à $Null ou ne répond pas aux critéres suivants :

# Si la validation demandée est stricte et que le type du paramètre est du type attendu -&gt; FIN
# Si la validation demandée est stricte et que le type du paramètre n'est pas du type attendu -&gt; Exception

# Si la validation demandée n'est pas stricte, que le type du paramètre est du type attendu et
# que le cast réussi -&gt; FIN
# Si la validation demandée n'est pas stricte, que le type du paramètre n'est pas du type attendu et
# que le cast échoue -&gt; Exception
# note : avec le type [string] dans ce cas le cast réussi toujours. Avec un number vers une Date aussi, etc.
#
# Si $TestEmptyString est indiqué et que $Type est égal à [String] on valide le contenu du paramètre de type chaîne
# S'il est vide -&gt; Exception
# sinon -&gt;Suite
#
# Exception : ArgumentTransformationMetadataException
#
# Test-Variable (gv NomDeVariable) String -strict -TestEmptyString
# Test-Variable (gv NomDeVariable) DateTime -TestEmptyString


Write-Debug (\&quot;Call : {0}\&quot; -F $MyInvocation.InvocationName)
#récupère le contexte d'appel de l'appelant
$ParentInvocation = (Get-Variable MyInvocation -Scope 1).Value
$CS=\&quot;{0}.{1}\&quot; -F $ParentInvocation.MyCommand,$MyInvocation.MyCommand

if ($Variable -eq $null) {Throw \&quot;$CS : le paramètre Variable est à null.\&quot;}
if ($Type -eq $null) {Throw \&quot;$CS : le paramètre Type est à null.\&quot;}
Write-debug $Variable.Name
if ($Variable.Value -ne $null)
{Write-debug \&quot;$($Variable.Value.GetType())\&quot;}
else
{
Write-debug \&quot;`Le paramètre $($Variable.Name) est à `$null.\&quot;
Throw \&quot;$CS : La valeur du paramètre $($Variable.Name) est `$null.\&quot;
}
Write-debug \&quot;$Variable.Value\&quot;
Write-debug \&quot;$Type\&quot;
if ($TestEmptyString -and ($Type -eq [String]) )
{if ($Variable.Value -eq [string]::Empty)
{Throw \&quot;$CS : Le contenu du paramètre $($Variable.Name) n'est pas renseigné.\&quot;}
}
#$host.EnterNestedPrompt()

#Le paramètre reçu est-il du type attendu ?
$isSameType=$Variable.Value -is $Type

#Peut-on caster la valeur reçue dans le type attendu ?
#En cas de cast impossible, l'opérateur -as appel la méthode ToString()
#Ce qui reste cohérent avec le parsing de PowerShell.
#Si le paramètre attendu est de type [string], dans ce cas une date sera transformée en string.
#Le cast du paramètre en un type [string] réussira toujours !
$isCastFail=($Variable.Value -as $Type) -eq $null

Write-debug \&quot;$isNotSameType : $isNotSameType\&quot;
Write-debug \&quot;isCastFail : $isCastFail\&quot;

#Si le cast demandé est strict, le type du paramètre doit être celui du type attendu
#ou
#si le cast demandé n'est pas strict que le type du paramètre n'est pas celui du type attendu et que le cast échoue.
if ( ($Strict.IsPresent -and !$isSameType) -or (!$Strict.IsPresent -and !$isSameType -and $isCastFail) )
{
$StrFrm=\&quot;$CS : Impossible de convertir la valeur du paramètre {0} « {1} » en type « {2} ».\&quot;
$Ex= new-object System.Management.Automation.ArgumentTransformationMetadataException (
$StrFrm -F $Variable.Name,$Variable.Value.GetType(),$Type.ToString() )
throw $Ex
}
} #Test-Variable
[/code:1]
Le code d'appel est simplifié, mais on doit utiliser Get-Variable. Ce cmdlet renvoi une instance du type PSVariable, contenant le nom et le contenu de la variable indiquée.
[code:1]
Function SendMail( $attach)
{
Test-Variable (gv attach) String -TestEmptyString
if (! (Test-path $Attach)) {Throw \&quot;Le fichier n'existe pas : $Attach\&quot;}
$Attach
\&quot;Send mail\&quot;
}[/code:1]<br><br>Message édité par: Laurent Dardenne, à: 1/02/09 21:27

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 16 ans 5 mois #5475 par Laurent Dardenne
On prend les mêmes et on recommence, cette fois-ci avec la v2 RTM.

Déterminer si un paramètre prend une valeur par défaut :
[code:1]Function Test-UnBoundArguments
{
param([String] $Name,[int]$Nombre=3,[switch] $Stop)

#$localInvocation=$MyInvocation
#$localPSB=$PSBoundparameters
$OutValue = $null
if ($MyInvocation.BoundParameters.TryGetValue('Nombre', [ref]$OutValue))
{
if ($OutValue -eq $null)
{Write-Warning \&quot;Le paramètre Nombre prend la valeur `$null.\&quot;}
else
{Write-Warning \&quot;Le paramètre Nombre est précisé et prend la valeur $OutValue.\&quot;}
}
else
{
Write-Warning \&quot;Le paramètre Nombre n'est pas précisé mais prend la valeur par défaut.\&quot;
}

\&quot;Nombre =$Nombre\&quot;
}

Test-UnBoundArguments
Test-UnBoundArguments -name \&quot;Test\&quot;

Test-UnBoundArguments \&quot;Test\&quot;
Test-UnBoundArguments \&quot;Test\&quot; 5
Test-UnBoundArguments \&quot;Test\&quot; $null
Test-UnBoundArguments \&quot;Test\&quot; -nombre $null
Test-UnBoundArguments \&quot;Test\&quot; -nombre[/code:1]
Déterminer les paramètres inconnus.
[code:1]
Function Test-UnBoundArguments
{
param([String] $Name,[int]$Nombre=3,[switch] $Stop)

#$localInvocation=$MyInvocation
#$localPSB=$PSBoundparameters

Write-host \&quot; ---- BoundParameters\&quot;
$MyInvocation.BoundParameters
#Write-host \&quot; ---- PSBoundParameters\&quot;
# $PSBoundparameters pointe sur $MyInvocation.BoundParameters
# Faire : $MyInvocation.BoundParameters.Clear()...
#$PSBoundparameters
Write-host \&quot; ---- \&quot;


Write-host \&quot; ---- UnboundArguments\&quot;
$MyInvocation.UnboundArguments

# List&lt;Object&gt;
#$MyInvocation.UnboundArguments.Psbase

#$host.EnterNestedPrompt()
#Les éléments de la liste sont accesssibles par $MyInvocation.UnboundArguments.Item($I)
$Count=
if ($MyInvocation.UnBoundArguments.Count -gt 0)
{
Throw \&quot;Le ou les paramètres suivants sont inconnus : $($MyInvocation.UnBoundArguments).\&quot;
}

\&quot;Nombre =$Nombre\&quot;
}
Test-UnBoundArguments -ParamInconnu 10

Test-UnBoundArguments -nime \&quot;Test\&quot;

Test-UnBoundArguments -Stop

Test-UnBoundArguments -SwitchInconnu -hInconnu -ParamInconnu 10
Test-UnBoundArguments -SwitchInconnu -hInconnu Test-UnBoundArguments -ParamInconnu 10
Test-UnBoundArguments -SwitchInconnu

Test-UnBoundArguments -SwitchInconnu:$False
$truc=$true
Test-UnBoundArguments -SwitchInconnu:$truc
$truc=10
Test-UnBoundArguments -SwitchInconnu:$truc[/code:1]
Notez que la variable $PSBoundparameters pointe sur $MyInvocation.BoundParameters. Pour le vérifier faire : [code:1]
$PSBoundparameters
$MyInvocation.BoundParameters.Clear()
$PSBoundparameters
[/code:1]

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.088 secondes
Propulsé par Kunena