256 votes

Valeur de retour de la fonction dans PowerShell

J'ai développé une fonction PowerShell qui exécute un certain nombre d'actions impliquant le provisionnement. SharePoint Sites de l'équipe. En fin de compte, je veux que la fonction renvoie l'URL du site provisionné sous la forme d'une chaîne de caractères, donc à la fin de ma fonction, j'ai le code suivant :

$rs = $url.ToString();
return $rs;

Le code qui appelle cette fonction ressemble à ceci :

$returnURL = MyFunction -param 1 ...

Je m'attendais donc à un String, mais ce n'est pas le cas. Au lieu de cela, c'est un objet de type System.Management.Automation.PSMethod. Pourquoi renvoie-t-il ce type d'objet au lieu d'un type String ?

3 votes

Peut-on voir la déclaration de la fonction ?

1 votes

Non, pas l'invocation de la fonction, montrez-nous comment/où vous avez déclaré "MaFonction". Ce qui se passe quand vous le faites : La fonction "Get-Item" : \MyFunction

1 votes

J'ai suggéré une autre façon d'aborder cette question : stackoverflow.com/a/42842865/992301

340voto

Goyuix Points 9634

PowerShell a une sémantique de retour vraiment bizarre, du moins lorsqu'on l'envisage d'un point de vue de programmation plus traditionnel. Il y a deux idées principales à prendre en compte :

  • Toutes les sorties sont capturées et renvoyées
  • Le mot clé return indique simplement un point de sortie logique.

Ainsi, les deux blocs script suivants feront effectivement exactement la même chose :

$a = "Hello, World"
return $a

$a = "Hello, World"
$a
return

La variable $a dans le deuxième exemple est laissée en sortie sur le pipeline et, comme mentionné, toute la sortie est retournée. En fait, dans le deuxième exemple, vous pourriez omettre complètement le retour et vous obtiendriez le même comportement (le retour serait implicite car la fonction se termine naturellement et sort).

Sans plus de détails sur la définition de votre fonction, je ne peux pas dire pourquoi vous obtenez un objet PSMethod. Je pense que vous avez probablement quelque chose quelques lignes plus haut qui n'est pas capturé et qui est placé dans le pipeline de sortie.

Il convient également de noter que vous probablement n'ont pas besoin de ces points-virgules, sauf si vous imbriquez plusieurs expressions sur une seule ligne.

Vous pouvez en savoir plus sur la sémantique des retours sur le site Web de la Commission européenne. about_Return sur TechNet, ou en invoquant l'option help return à partir de PowerShell lui-même.

21 votes

Existe-t-il un moyen de retourner une valeur de curseur à partir d'une fonction ?

0 votes

Je ne suis pas tout à fait sûr de ce que vous entendez par valeur scalaire. Par exemple, le code suivant renvoie une valeur scalaire : function Return-One { 1 } - vous pourriez faire des choses similaires avec n'importe quelle valeur "scalaire" : chaînes de caractères, nombres, booléens, etc...

13 votes

Si votre fonction renvoie une table de hachage, alors elle traitera le résultat comme tel, mais si vous "echo" n'importe quoi dans le corps de la fonction, y compris la sortie d'autres commandes, et soudain le résultat est mixte.

71voto

Luke Puplett Points 4971

Cette partie de PowerShell est probablement l'aspect le plus stupide. Toute sortie étrangère générée pendant une fonction polluera le résultat. Parfois, il n'y a pas de sortie, et puis dans certaines conditions, il y a une autre sortie non planifiée, en plus de votre valeur de retour planifiée.

Je supprime donc l'affectation de l'appel de fonction d'origine, de sorte que la sortie se retrouve à l'écran, puis j'avance jusqu'à ce que quelque chose que je n'avais pas prévu apparaisse dans la fenêtre du débogueur (à l'aide de la fonction PowerShell ISE ).

Même des choses comme la réservation de variables dans des scopes externes provoquent des sorties, comme par exemple [boolean]$isEnabled qui crachera un faux de manière ennuyeuse à moins que vous ne le fassiez [boolean]$isEnabled = $false .

Un autre bon exemple est $someCollection.Add("thing") qui affiche le nouveau nombre de collections.

2 votes

Pourquoi se contenter de réserver un nom au lieu de faire la meilleure pratique qui consiste à initialiser correctement la variable avec une valeur explicitement définie.

0 votes

C'était juste un exemple d'une opération qui génère des résultats inattendus. Mais personnellement, je suis un développeur C#, donc c'est juste une habitude.

2 votes

Je suppose que vous voulez dire que vous avez un bloc de déclarations de variables au début de chaque portée pour chaque variable utilisée dans cette portée. Vous devriez toujours, ou peut-être déjà, initialiser toutes les variables avant de les utiliser dans n'importe quel langage, y compris C#. Il est également important de faire [boolean]$a dans powershell ne déclare pas réellement la variable $a. Vous pouvez le confirmer en suivant cette ligne avec la ligne $a.gettype() et comparez ce résultat à celui obtenu lorsque vous déclarez et initialisez avec la chaîne de caractères $a = [boolean]$false .

45voto

Jonesy Points 31

Comme solution de rechange, j'ai retourné le dernier objet du tableau que vous obtenez de la fonction... Ce n'est pas une grande solution, mais c'est mieux que rien :

someFunction {
   $a = "hello"
   "Function is running"
   return $a
}

$b = someFunction
$b = $b[($b.count - 1)]  # Or
$b = $b[-1]              # Simpler

En somme, on pourrait écrire la même chose en une seule ligne :

$b = (someFunction $someParameter $andAnotherOne)[-1]

8 votes

$b = $b[-1] serait un moyen plus simple de récupérer le dernier élément du tableau, mais encore plus simple serait de ne pas sortir les valeurs que vous ne voulez pas.

1 votes

@Duncan Et que se passe-t-il si je veux produire le contenu de la fonction, tout en ayant une valeur de retour ?

0 votes

@ThoAppelsin si vous voulez dire que vous voulez écrire des choses dans le terminal alors utilisez write-host pour l'éditer directement.

5voto

Shay Levy Points 41404

C'est difficile à dire sans regarder le code. Assurez-vous que votre fonction ne renvoie pas plus d'un objet et que vous capturez tous les résultats des autres appels. Qu'est-ce que vous obtenez pour :

@($returnURL).count

Quoi qu'il en soit, deux suggestions :

Transforme l'objet en chaîne de caractères :

...
return [string]$rs

Ou alors, mettez-le entre guillemets, comme ci-dessus, mais plus court à taper :

...
return "$rs"

1 votes

Ou même simplement "$rs" - le return n'est requis que lors du retour anticipé de la fonction. L'absence de retour est un meilleur idiome PowerShell.

4voto

Edwin Points 11

Ce qui suit renvoie simplement 4 comme réponse. Lorsque vous remplacez les expressions d'addition par des chaînes de caractères, elle renvoie la première chaîne.

Function StartingMain {
  $a = 1 + 3
  $b = 2 + 5
  $c = 3 + 7
  Return $a
}

Function StartingEnd($b) {
  Write-Host $b
}

StartingEnd(StartingMain)

Cela peut également être fait pour un tableau. L'exemple ci-dessous retournera "Texte 2".

Function StartingMain {
  $a = ,@("Text 1","Text 2","Text 3")
  Return $a
}

Function StartingEnd($b) {
  Write-Host $b[1]
}

StartingEnd(StartingMain)

Notez que vous devez appeler la fonction en dessous de la fonction elle-même. Sinon, lors de sa première exécution, elle renverra une erreur indiquant qu'elle ne sait pas ce qu'est "StartingMain".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X