Ich habe eine PowerShell-Funktion entwickelt, die eine Reihe von Aktionen zum Bereitstellen von SharePoint Team-Websites ausführt . Letztendlich möchte ich, dass die Funktion die URL der bereitgestellten Site als Zeichenfolge zurückgibt, sodass ich am Ende meiner Funktion den folgenden Code habe:
$rs = $url.ToString();
return $rs;
Der Code, der diese Funktion aufruft, sieht folgendermaßen aus:
$returnURL = MyFunction -param 1 ...
Ich erwarte also einen String, aber das ist es nicht. Stattdessen handelt es sich um ein Objekt vom Typ System.Management.Automation.PSMethod. Warum wird dieser Typ anstelle eines String-Typs zurückgegeben?
powershell
ChiliYago
quelle
quelle
Antworten:
PowerShell hat eine wirklich verrückte Rückkehrsemantik - zumindest aus einer traditionelleren Programmierperspektive. Es gibt zwei Hauptideen, um den Kopf herumzureißen:
Somit bewirken die folgenden zwei Skriptblöcke genau dasselbe:
Die Variable $ a im zweiten Beispiel bleibt als Ausgabe in der Pipeline und wie erwähnt wird die gesamte Ausgabe zurückgegeben. Tatsächlich könnten Sie im zweiten Beispiel die Rückgabe vollständig weglassen und das gleiche Verhalten erhalten (die Rückgabe würde impliziert, wenn die Funktion auf natürliche Weise abgeschlossen und beendet wird).
Ohne mehr von Ihrer Funktionsdefinition kann ich nicht sagen, warum Sie ein PSMethod-Objekt erhalten. Ich vermute, dass Sie wahrscheinlich ein paar Zeilen haben, die nicht erfasst und in die Ausgabepipeline eingefügt werden.
Es ist auch erwähnenswert, dass Sie wahrscheinlich diese Semikolons nicht benötigen - es sei denn, Sie verschachteln mehrere Ausdrücke in einer einzelnen Zeile.
Weitere Informationen zur Rückgabesemantik finden Sie auf der Seite about_Return in TechNet oder durch Aufrufen des
help return
Befehls in PowerShell.quelle
write-debug
$DebugPreference = "Continue"
"SilentlyContinue"
echo
war das Problem für mich! Dieser kleine Nebenpunkt ist sehr, sehr wichtig. Ich gab eine Hashtabelle zurück und folgte allem anderen, aber der Rückgabewert war immer noch nicht das, was ich erwartet hatte. Entfernte dasecho
und arbeitete wie ein Zauber.Dieser Teil von PowerShell ist wahrscheinlich der dümmste Aspekt. Jede fremde Ausgabe, die während einer Funktion erzeugt wird, verschmutzt das Ergebnis. Manchmal gibt es keine Ausgabe, und unter bestimmten Bedingungen gibt es zusätzlich zu Ihrem geplanten Rückgabewert eine andere ungeplante Ausgabe.
Daher entferne ich die Zuweisung aus dem ursprünglichen Funktionsaufruf, sodass die Ausgabe auf dem Bildschirm angezeigt wird, und gehe dann durch, bis etwas, das ich nicht geplant hatte, im Debugger-Fenster angezeigt wird (mithilfe der PowerShell ISE ).
Sogar Dinge wie das Reservieren von Variablen in äußeren Bereichen verursachen eine Ausgabe,
[boolean]$isEnabled
die nervig ein False ausspuckt, wenn Sie es nicht machen[boolean]$isEnabled = $false
.Eine andere gute ist,
$someCollection.Add("thing")
die die neue Sammlungsanzahl ausspuckt.quelle
[boolean]$a
in Powershell die Variable $ a nicht deklariert wird. Sie können dies bestätigen, indem Sie dieser Zeile mit der Zeile folgen$a.gettype()
und diese Ausgabe mit der Deklaration und Initialisierung mit der Zeichenfolge vergleichen$a = [boolean]$false
.>
und<
werden bereits für die Umleitung von E / A-Streams zu / von Dateien verwendet.>=
schreibt stdout in eine Datei namens=
.Mit PowerShell 5 können wir jetzt Klassen erstellen. Ändern Sie Ihre Funktion in eine Klasse, und return gibt nur das Objekt unmittelbar davor zurück. Hier ist ein wirklich einfaches Beispiel.
Wenn dies eine Funktion wäre, wäre die erwartete Ausgabe
Als Klasse wird jedoch nur die Ganzzahl 808979 zurückgegeben. Eine Klasse ist eine Art Garantie dafür, dass nur der deklarierte oder ungültige Typ zurückgegeben wird.
quelle
static
Methoden unterstützt .[test_class]::return_what()
return 808979
Funktion oder nicht.Write-Output
? Es ist nicht die "Konsolen" -Ausgabe, auf die hier Bezug genommen wird, sondern die Ausgabe für die Funktion / das Cmdlet. Wenn Sie Material auf der Konsole auszugeben wollen , gibt esWrite-Verbose
,Write-Host
undWrite-Error
Funktionen, unter anderem. GrundsätzlichWrite-Output
ist näher an derreturn
Semantik als an einer Konsolenausgabeprozedur. Missbrauche es nicht, benutze esWrite-Verbose
für Ausführlichkeit, dafür ist es da.Um dieses Problem zu umgehen, habe ich das letzte Objekt im Array zurückgegeben, das Sie von der Funktion erhalten haben. Es ist keine großartige Lösung, aber es ist besser als nichts:
Alles in allem könnte eine einzeiligere Art, dasselbe zu schreiben, sein:
quelle
$b = $b[-1]
Dies wäre eine einfachere Möglichkeit, das letzte Element oder das Array abzurufen. Noch einfacher wäre es jedoch, keine Werte auszugeben, die Sie nicht möchten.write-host
es direkt auszugeben.Ich übergebe ein einfaches Hashtable-Objekt mit einem einzelnen Ergebniselement, um die Rückkehrverrücktheit zu vermeiden, da ich auch auf der Konsole ausgeben möchte. Es wirkt durch Referenzübergabe.
Sie können eine echte Beispielverwendung in meinem GitHub-Projekt unpackTunes sehen .
quelle
Es ist schwer zu sagen, ohne sich den Code anzusehen. Stellen Sie sicher, dass Ihre Funktion nicht mehr als ein Objekt zurückgibt und dass Sie alle Ergebnisse anderer Aufrufe erfassen. Wofür bekommst du:
Wie auch immer, zwei Vorschläge:
Wandeln Sie das Objekt in einen String um:
Oder schließen Sie es einfach in doppelte Anführungszeichen ein, wie oben, aber kürzer zu tippen:
quelle
"$rs"
- dasreturn
ist nur erforderlich, wenn Sie frühzeitig von der Funktion zurückkehren. Das Auslassen der Rückgabe ist eine bessere PowerShell-Sprache.Lukes Beschreibung der Funktionsergebnisse in diesen Szenarien scheint richtig zu sein. Ich möchte nur die Grundursache verstehen und das PowerShell-Produktteam würde etwas gegen das Verhalten unternehmen. Es scheint ziemlich häufig zu sein und hat mich zu viel Debugging-Zeit gekostet.
Um dieses Problem zu umgehen, habe ich globale Variablen verwendet, anstatt den Wert aus dem Funktionsaufruf zurückzugeben und zu verwenden.
Hier ist eine weitere Frage zur Verwendung globaler Variablen: Festlegen einer globalen PowerShell-Variablen aus einer Funktion, bei der der globale Variablenname eine an die Funktion übergebene Variable ist
quelle
Das Folgende gibt einfach 4 als Antwort zurück. Wenn Sie die Add-Ausdrücke für Zeichenfolgen ersetzen, wird die erste Zeichenfolge zurückgegeben.
Dies kann auch für ein Array erfolgen. Das folgende Beispiel gibt "Text 2" zurück.
Beachten Sie, dass Sie die Funktion unterhalb der Funktion selbst aufrufen müssen. Andernfalls wird beim ersten Ausführen ein Fehler zurückgegeben, der nicht weiß, was "StartingMain" ist.
quelle
Die vorhandenen Antworten sind korrekt, aber manchmal geben Sie etwas nicht explizit mit a
Write-Output
oder a zurückreturn
, aber die Funktionsergebnisse enthalten einen mysteriösen Wert. Dies könnte die Ausgabe einer eingebauten Funktion wie seinNew-Item
Das zusätzliche Rauschen bei der Verzeichniserstellung wird gesammelt und in der Ausgabe ausgegeben. Die einfache Möglichkeit, dies zu mildern, besteht darin
| Out-Null
, das Ende derNew-Item
Anweisung hinzuzufügen , oder Sie können das Ergebnis einer Variablen zuweisen und diese Variable einfach nicht verwenden. Es würde so aussehen ...New-Item
ist wahrscheinlich die bekannteste von diesen, aber andere umfassen alleStringBuilder.Append*()
Methoden sowie dieSqlDataAdapter.Fill()
Methode.quelle
Als Alternative
return
würde ich vorschlagenWrite-Output
.Write-Output
Sie können Eingaben aus der Pipeline übernehmen und entweder über die Pipeline weiterleiten oder an die Konsole drucken, wenn dies der letzte Befehl ist.Beendet
Write-Output
das Skript jedoch nicht wiereturn
gewohnt, was von Vorteil sein kann, wenn die Ausgabe in einer Schleife verwendet, weitergeleitet usw. werden soll.quelle