J'ai écrit la fonction "A" qui appellera l'une des nombreuses autres fonctions. Pour enregistrer la fonction de réécriture 'A', je voudrais passer la fonction à appeler comme paramètre de la fonction 'A'. Par exemple:
function A{
Param($functionToCall)
Write-Host "I'm calling : $functionToCall"
}
function B{
Write-Host "Function B"
}
Function C{
write-Host "Function C"
}
A -functionToCall C
Retours: j'appelle: C
Je m'attends à ce qu'il revienne: j'appelle: Fonction C.
J'ai essayé différentes choses telles que:
Param([scriptblock]$functionToCall)
Impossible de convertir System.String en ScriptBlock
A -functionToCall $function:C
Renvoie la fonction "Write-Host" C "
A - functionToCall (&C)
Cela évalue avant le reste:
Function C
I'm Calling :
Je suis sûr que c'est de la programmation 101, mais je ne peux pas trouver la bonne syntaxe ou ce que je fais mal.
Est-ce ce dont vous avez besoin?
function A{
Param($functionToCall)
Write-Host "I'm calling : $functionToCall"
#access the function-object like this.. Ex. get the value of the StartPosition property
(Get-Item "function:$functionToCall").ScriptBlock.StartPosition
}
function B{
Write-Host "Function B"
}
Function C{
write-Host "Function C"
}
PS> a -functionToCall c
I'm calling : c
Content : Function C{
write-Host "Function C"
}
Type : Position
Start : 307
Length : 43
StartLine : 14
StartColumn : 1
EndLine : 16
EndColumn : 2
Je ne suis pas sûr que ce soit le meilleur, mais:
function A{
Param([scriptblock]$FunctionToCall)
Write-Host "I'm calling $($FunctionToCall.Invoke(4))"
}
function B($x){
Write-Output "Function B with $x"
}
Function C{
Param($x)
Write-Output "Function C with $x"
}
PS C:\WINDOWS\system32> A -FunctionToCall $function:B
I'm calling Function B with 4
PS C:\WINDOWS\system32> A -FunctionToCall $function:C
I'm calling Function C with 4
PS C:\WINDOWS\system32> A -FunctionToCall { Param($x) "Got $x" }
I'm calling Got x
Avez-vous pensé à passer un ScriptBlock comme paramètre?
$scriptBlock = { Write-Host "This is a script block" }
Function f([ScriptBlock]$s) {
Write-Host "Invoking ScriptBlock: "
$s.Invoke()
}
PS C:\> f $scriptBlock
Invoking ScriptBlock:
This is a script block
Si vous voulez vraiment passer le nom d'une fonction, comme chaîne: utilisez &
, Le - opérateur d'appel, pour l'invoquer:
function A {
Param($functionToCall)
# Note the need to enclose a command embedded in a string in $(...)
Write-Host "I'm calling: $(& $functionToCall)"
}
Function C {
"Function C" # Note: Do NOT use Write-Host to output *data*.
}
A -functionToCall C
En ce qui concerne la nécessité d'utiliser $(...)
à l'intérieur de "..."
: Voir cette réponse , qui explique les règles d'expansion de chaîne (interpolation de chaîne) de PowerShell.
Ce qui précède donne I'm calling: Function C
Notez comment la fonction C
utilise la sortie implicite (identique à l'utilisation explicite de Write-Output
) Pour renvoyer une valeur.Write-Host
Est généralement le mauvais outil à utiliser , sauf si l'intention est d'écrire explicitement sur l'écran uniquement, en contournant les flux de sortie de PowerShell.
Vous avez généralement besoin de l'opérateur &
Dans les scénarios suivants:
Pour appeler une commande par nom ou chemin, via un référence de variable et/ou si le nom est entre guillemets simples ou doubles.
Pour appeler un bloc de script.
Les blocs de script sont le moyen préféré de passer des morceaux de code dans PowerShell; ce qui précède pourrait être réécrit en (notez que le mécanisme d'invocation ne change pas, juste l'argument passé):
function A {
Param($scriptBlockToCall)
Write-Host "I'm calling: $(& $scriptBlockToCall)"
}
Function C {
"Function C" # Note: Do NOT use Write-Host to output *data*.
}
A -scriptBlockToCall { C }
Dans les deux cas, pour passer arguments, placez-les simplement après: & <commandNameOrScriptBlock>
; notez comment splatting (@<var>
) est utilisé pour passer les arguments non liés stockés dans la variable automatique $Args
.
function A {
Param($commandNameOrScriptBlockToCall)
Write-Host "I'm calling: $(& $commandNameOrScriptBlockToCall @Args)"
}
Function C {
"Function C with args: $Args"
}
A -commandNameOrScriptBlockToCall C one two # by name
A -commandNameOrScriptBlockToCall { C @Args } one two # by script block
Ce qui précède donne deux fois I'm calling: Function C with args: one two
.
La solution de Duncan a très bien fonctionné pour moi. Cependant, je rencontre certains problèmes lorsque le nom de la fonction contient un tiret.
J'ai pu contourner ce problème en construisant son troisième exemple:
function A{
Param([scriptblock]$functionToCall)
Write-Host "I'm calling $($functionToCall.Invoke(4))"
}
function Execute-FunctionWithDash($x)
{
Write-Output "Function Execute-FunctionWithDash with $x"
}
PS C:\WINDOWS\system32> A -functionToCall { Param($x) Execute-FunctionWithDash $x }
I'm calling Function Execute-FunctionWithDash with 4
function strdel($a,$b,$c) {
return ($a.substring(0,$b)+$(substr $a $c $a.length))
}
function substr($a,$b,$c) {
return $a.substring($b,($c-$b))
}
$string = "Bark in the woods"
$in = $(substr $(strdel $string 0 5) 0 2)
write-Host $in
Où Function 'substr' appelait la fonction 'strdel' comme paramètre $ a.
Fonctions de https://github.com/brandoncomputer/vds
pour transmettre un nombre variable de paramètres nommés
function L($Lambda){
write-Host "`nI'm calling $Lambda"
write-Host "`nWith parameters"; ft -InputObject $Args
& $Lambda @Args
}
semble bien fonctionner avec des noms de fonction étranges
function +Strange-Name($NotUsed,$Named1,$Named2){
ls -filter $Named1 -Attributes $Named2
}
PS C:\>L +Strange-Name -Named1 *.txt -Named2 Archive
et les fichiers exe ainsi
PS C:\>L grep.exe ".*some text.*" *.txt
bien qu'il semble que vous ayez encore besoin de faire attention à l'injection
function inject($OrigFunction){
write-Host 'pre-run injection'
& $OrigFunction @Args
write-Host 'post-run injection'
}
PS C:\>L inject +Strange-Name -Named1 *.txt -Named2 Archive
Que diriez-vous:
function A{
Param($functionToCall)
$res = Invoke-Command $functionToCall
Write-Host "I'm calling : $res"
}
function B{
"Function B"
}
Function C{
"Function C"
}
A -functionToCall ${function:C}
Parcourez la fonction en tant que valeur à l'aide de $ {function: ...}. Appelez la fonction et enregistrez les résultats dans $ res.