8
votes

Comment créer de manière dynamique des fonctions accessibles dans une portée parentale?

Voici un exemple:

function ChildF()
{
  #Creating new function dynamically
  $DynFEx =
@"
  function DynF()
  {
    "Hello DynF"
  }
"@
  Invoke-Expression $DynFEx
  #Calling in ChildF scope Works
  DynF 
}
ChildF
#Calling in parent scope doesn't. It doesn't exist here
DynF


0 commentaires

5 Réponses :


9
votes

Vous pouvez mettre en place la fonction avec le mot-clé global : xxx


1 commentaires

Dans le code donné ci-dessus, fonction globale: dynf {...} a probablement plus de sens. ;-).



13
votes

Une autre option serait d'utiliser la fonction Set-item -Path: Global: Childfunction -Value {...}

Utilisation de SET-Item , vous pouvez transmettre une chaîne ou un bloc de script à la valeur de la définition de la fonction.


1 commentaires

Passer un block de script à -Value fonctionne bien, mais en passant une chaîne fait pas fonctionne comme prévu: tandis que < Code> Set-item l'accepte, appelant la fonction, puis simplement écho la chaîne de définition avec les accessoires bouclés dépouillé. Vous pouvez contourner cela avec & , mais c'est gênant et je ne sais pas si elle a des effets secondaires (par exemple, Fonction d'élément de jeu: FOO "& {'Arg 0:' + $ args [0]} @args "; foo 'hi' - mieux utiliser Invoke-expression Si vous devez créer le corps de la fonction dans une chaîne .



9
votes

Les autres solutions sont de meilleures réponses à la question spécifique. Cela dit, il est bon d'apprendre le moyen le plus général de créer des variables globales: xxx

lire "Aide environ_scopes" pour des tonnes Plus d'informations.


0 commentaires

2
votes

Un moyen plus correct et fonctionnel de le faire serait de renvoyer le corps de fonction sous forme de bloc de script, puis de le recomposer.

function ChildF() {
    function DynF() {
        "Hello DynF"
    }
    return ${function:DynF}
}
$DynFEx = ChildF
Invoke-Expression -Command "function DynF { $DynFEx }"
DynF


0 commentaires

0
votes

Merci à la poste de Richard. Gardé avoir des problèmes de faire cette chose simple. J'ai révisé pour avoir transmis une fonction de local à distance.

#Method 1 Load the function from disk    
$getCert = gc 'C:\MyScripts\getCert.ps1'
Invoke-Command $RemoteSrv -ScriptBlock {Set-Variable -name DefFN -value ($Args -join "`n") -scope global ; Invoke-Expression $DefFn } -ArgumentList $getCert
    
#Method 2 Load the function from local definition of function
Invoke-Command $RemoteSrv -ScriptBlock {Set-Variable -name DefFN -value ($Args -join "`n") -scope global ; Invoke-Expression $DefFn } -ArgumentList ('Function GetCert {'+(Get-Command GetCert).Definition+'}')

#Remote server now has function
Invoke-Command $RemoteSrv -ScriptBlock {getcert stackoverflow.com}

URL        : stackoverflow.com
Expires    : 12/14/2021 8:07:08 AM
SAN        : DNS Name=*.askubuntu.com, DNS Name=.....
Thumbprint : ec0055be478411bafe98d11d63a5c9279ff0e173
IP         : 151.101.193.69
Handle     : 2866249748176
Issuer     : CN=R3, O=Let's Encrypt, C=US
Subject    : CN=*.stackexchange.com


0 commentaires