Valeur de retour de la fonction dans PowerShell

j'ai développé une fonction PowerShell qui effectue un certain nombre d'actions impliquant l'approvisionnement SharePoint les sites D'équipe. En fin de compte, je veux que la fonction renvoie L'URL du site fourni comme 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 à:

$returnURL = MyFunction -param 1 ...

donc j'attends une ficelle, mais ce n'est pas le cas. Au lieu de cela, il est un objet du système de type.Gestion.Automatisation.PSMethod. Pourquoi renvoie-t-il ce type au lieu d'un type String?

135
demandé sur Peter Mortensen 2012-04-23 22:28:39

8 réponses

PowerShell a vraiment une sémantique de retour farfelue - du moins si l'on considère la programmation d'un point de vue plus traditionnel. Il y a deux idées principales pour envelopper votre tête:

  • toute la sortie est capturée, et retournée
  • le mot-clé return indique simplement un point de sortie logique

ainsi, les deux blocs de script suivants feront effectivement la même chose:

$a = "Hello, World"
return $a

$a = "Hello, World"
$a
return

la variable $a dans le second exemple est laissée comme 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 termine et sort naturellement).

sans plus de définition de votre fonction Je ne peux pas dire pourquoi vous obtenez un objet PSMethod. Ma conjecture est que vous avez probablement avoir quelque chose quelques lignes qui n'est pas d'être capturé et est placé sur la sortie du pipeline.

Il est également intéressant de noter que vous probablement n'a pas besoin des points-virgules - sauf si vous êtes imbrication de plusieurs expressions sur une seule ligne.

vous pouvez en savoir plus sur la sémantique du retour sur la page about_Return sur TechNet, ou en invoquant la commande help return de PowerShell elle-même.

205
répondu Goyuix 2012-04-23 21:01:56

cette partie de PowerShell est probablement l'aspect le plus stupide. Toute sortie externe générée au cours d'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 prévue.

donc, ce que je fais est de supprimer l'affectation de l'appel de la fonction originale afin que la sortie se termine à l'écran, et puis passer à travers jusqu'à ce que quelque chose que je n'ai pas prévu pour pops out dans le fenêtre de débogage (utilisant la PS ISE).

même les choses comme la réservation des variables dans les lunettes extérieures causent la sortie, comme [boolean]$isEnabled qui sera fâcheusement cracher un False out à moins que vous le faites [boolean]$isEnabled = $false .

un autre bon est $someCollection.Add("thing") qui crache le nouveau compte de collection.

35
répondu Luke Puplett 2016-12-29 14:27:34

avec PowerShell 5 nous avons maintenant la possibilité de créer des classes. Changer votre fonction en classe peut non seulement vous pouvez la taper et retourner ne retournera que l'objet qui la précède immédiatement. Voici un exemple simple.

class test_class{
    [int]return_what() {
        $a = "Hello World"
        return 808979
    }
}
$tc = New-Object -TypeName test_class
$tc.return_what()

S'il s'agissait d'une fonction, le résultat escompté serait

Hello World
808979

mais en tant que classe la seule chose retournée est un INT 808979. Une classe est une sorte de garantie qu'elle ne reviendra le type déclaré ou invalide.

23
répondu DaSmokeDog 2017-03-12 02:46:34

comme solution de contournement, j'ai retourné le dernier objet dans le tableau que vous récupérez de la fonction... 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
20
répondu Jonesy 2016-05-17 06:12:51

je passe autour d'un simple objet Hashtable avec un seul membre de résultat pour éviter la folie de retour car je veux aussi sortir sur la console. Il agit par l'intermédiaire de passer par référence.

function sample-loop($returnObj) {
  for($i = 0; $i -lt 10; $i++) {
    write-host "loop counter: $i"
    $returnObj.result++
  }
}

function main-sample() {
  $countObj = @{ result = 0 }
  sample-loop -returnObj $countObj
  write-host "_____________"
  write-host "Total = " ($countObj.result)
}

main-sample

Vous pouvez voir un exemple réel d'utilisation à mon projet GitHub unpackTunes

5
répondu What Would Be Cool 2015-08-23 23:27:31

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

@($returnURL).count

en tout cas, deux suggestions:

convertir l'objet string:

...
return [string]$rs

ou simplement l'entourer de doubles guillemets, comme ci-dessus mais plus court pour taper:

...
return "$rs"
4
répondu Shay Levy 2012-04-23 21:02:33

la description de Luke des résultats de la fonction dans ces scénarios semble être droite sur. Vouloir seulement comprendre la cause profonde et L'équipe de produits PowerShell ferait quelque chose au sujet du comportement, semble être assez commun et a coûté trop de temps de débogage.

pour contourner ce problème, j'ai utilisé des variables globales plutôt que de retourner et d'utiliser la valeur de L'appel de fonction.

Voici un autre fil sur l'utilisation de Global variable: paramétrage d'une variable globale PowerShell à partir d'une fonction où le nom de la variable globale est une variable passée à la fonction

4
répondu Ted B. 2017-05-23 11:47:16

renvoie simplement 4 comme réponse. Lorsque vous remplacez les expressions add pour les chaînes, 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 aussi être fait pour un tableau. L'exemple ci-dessous retournera "Text 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 au-dessous de la fonction elle-même sinon la première fois qu'elle s'exécute elle retournera une erreur qu'elle ne sait pas ce qu'est" StartingMain".

je ne espérons que cela aide.

3
répondu Edwin 2017-01-13 00:41:35