J'ai développé une fonction PowerShell qui effectue un certain nombre d'actions impliquant le provisionnement de sites d'équipe SharePoint . En fin de compte, je souhaite que la fonction renvoie l'URL du site mis en service sous forme de chaîne.Ainsi, à 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 ...
Donc j'attends un String, mais ce n'est pas le cas. Au lieu de cela, il s'agit d'un objet de type System.Management.Automation.PSMethod. Pourquoi renvoie-t-il ce type au lieu d'un type String?
powershell
ChiliYago
la source
la source
Réponses:
PowerShell a une sémantique de retour vraiment farfelue - du moins dans une perspective de programmation plus traditionnelle. Il y a deux idées principales pour comprendre:
Ainsi, les deux blocs de script suivants feront exactement exactement la même chose:
La variable $ a dans le deuxième exemple est laissée en sortie sur le pipeline et, comme mentionné, toute la sortie est renvoyée. En fait, dans le deuxième exemple, vous pouvez omettre complètement le retour et vous obtiendrez le même comportement (le retour serait implicite lorsque la fonction se termine et se termine naturellement).
Sans plus de votre définition de fonction, je ne peux pas dire pourquoi vous obtenez un objet PSMethod. Je suppose que vous avez probablement quelque chose de quelques lignes qui n'est pas capturé et qui est placé sur le pipeline de sortie.
Il est également intéressant de noter que vous n'avez probablement 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 de retour sur la page about_Return sur TechNet ou en appelant la
help return
commande à partir de PowerShell lui-même.la source
write-debug
après avoir défini la variable$DebugPreference = "Continue"
au lieu de"SilentlyContinue"
echo
était le problème pour moi! Ce petit point secondaire est très très important. Je retournais une table de hachage, en suivant tout le reste, mais la valeur de retour n'était toujours pas ce à quoi je m'attendais. Supprimé leecho
et a fonctionné comme un charme.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, puis dans certaines conditions, il y a une autre sortie non planifiée, en plus de votre valeur de retour prévue.
Donc, je supprime l'affectation de l'appel de fonction d'origine, de sorte que la sortie se termine à l'écran, puis je passe à travers jusqu'à ce que quelque chose que je n'avais pas prévu apparaisse dans la fenêtre du débogueur (en utilisant le PowerShell ISE ).
Même des choses comme la réservation de variables dans des portées externes provoquent une sortie, comme
[boolean]$isEnabled
qui crachera un faux à moins que vous ne le fassiez.[boolean]$isEnabled = $false
.Un autre bon est
$someCollection.Add("thing")
qui crache le nouveau nombre de collections.la source
[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 en comparant cette sortie au moment où vous déclarez et initialisez avec la chaîne$a = [boolean]$false
.>
et<
sont déjà utilisés pour la redirection de flux d'E / S vers / depuis des fichiers.>=
écrit stdout dans un fichier appelé=
.Avec PowerShell 5, nous avons désormais la possibilité de créer des classes. Changez votre fonction en classe et return ne retournera que l'objet qui la précède immédiatement. Voici un exemple vraiment simple.
S'il s'agissait d'une fonction, le résultat attendu serait
mais en tant que classe, la seule chose retournée est l'entier 808979. Une classe est un peu comme une garantie qu'elle ne retournera que le type déclaré ou nul.
la source
static
méthodes. Menant à la syntaxe[test_class]::return_what()
return 808979
, fonction ou non.Write-Output
? Ce n'est pas la sortie "console" qui est mentionnée ici, c'est la sortie de la fonction / cmdlet. Si vous voulez jeter des choses sur la console il y aWrite-Verbose
,Write-Host
et lesWrite-Error
fonctions, entre autres. Fondamentalement,Write-Output
est plus proche de lareturn
sémantique que d'une procédure de sortie de console. N'en abusez pas, utilisezWrite-Verbose
pour la verbosité, c'est à ça que ça sert .Pour contourner le problème, j'ai renvoyé le dernier objet du tableau que vous récupérez de la fonction ... Ce n'est pas une excellente solution, mais c'est mieux que rien:
Dans l'ensemble, une façon d'écrire la même chose pourrait être plus une ligne:
la source
$b = $b[-1]
serait un moyen plus simple d'obtenir le dernier élément ou le tableau, mais encore plus simple serait de ne pas afficher les valeurs que vous ne voulez pas.write-host
pour les sortir directement.Je passe autour d'un simple objet Hashtable avec un seul membre de résultat pour éviter la folie de retour car je veux également sortir sur la console. Il agit en passant par référence.
Vous pouvez voir un exemple d'utilisation réel sur mon projet GitHub unpackTunes .
la source
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 obtenus à partir d'autres appels. Qu'est-ce que vous obtenez pour:
Quoi qu'il en soit, deux suggestions:
Convertissez l'objet en chaîne:
Ou mettez-le simplement entre guillemets doubles, comme ci-dessus mais plus court à taper:
la source
"$rs"
- lereturn
n'est requis que lors du retour anticipé de la fonction. Laisser de côté le retour est un meilleur idiome PowerShell.La description par Luke des résultats de la fonction dans ces scénarios semble être juste. Je souhaite seulement comprendre la cause profonde et l'équipe produit PowerShell ferait quelque chose pour le comportement. Cela semble être assez courant et m'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 une autre question sur l'utilisation des variables globales: Définition d'une variable globale PowerShell à partir d'une fonction où le nom de la variable globale est une variable passée à la fonction
la source
Ce qui suit renvoie simplement 4 comme réponse. Lorsque vous remplacez les expressions d'ajout pour les chaînes, la première chaîne est renvoyée.
Cela peut également être fait pour un tableau. L'exemple ci-dessous renverra "Texte 2"
Notez que vous devez appeler la fonction sous la fonction elle-même. Sinon, la première fois qu'il s'exécute, il renverra une erreur indiquant qu'il ne sait pas ce qu'est "StartingMain".
la source
Les réponses existantes sont correctes, mais parfois vous ne renvoyez pas quelque chose explicitement avec a
Write-Output
ou areturn
, mais il y a une valeur mystérieuse dans les résultats de la fonction. Cela pourrait être la sortie d'une fonction intégrée commeNew-Item
Tout ce bruit supplémentaire de la création du répertoire est collecté et émis dans la sortie. Le moyen le plus simple d'atténuer ce problème consiste à ajouter
| Out-Null
à la fin de l'New-Item
instruction, ou vous pouvez affecter le résultat à une variable et simplement ne pas utiliser cette variable. Cela ressemblerait à ceci ...New-Item
est probablement la plus célèbre d'entre elles, mais d'autres incluent toutes lesStringBuilder.Append*()
méthodes, ainsi que laSqlDataAdapter.Fill()
méthode.la source