Opracowałem funkcję PowerShell, która wykonuje szereg działań związanych z udostępnianiem witryn zespołu SharePoint . Ostatecznie chcę, aby funkcja zwróciła adres URL zabezpieczonej witryny jako ciąg znaków, więc na końcu mojej funkcji mam następujący kod:
$rs = $url.ToString();
return $rs;
Kod wywołujący tę funkcję wygląda następująco:
$returnURL = MyFunction -param 1 ...
Spodziewam się String, jednak tak nie jest. Zamiast tego jest to obiekt typu System.Management.Automation.PSMethod. Dlaczego zwraca ten typ zamiast typu String?
powershell
ChiliYago
źródło
źródło
Odpowiedzi:
PowerShell ma naprawdę zwariowaną semantykę zwrotów - przynajmniej patrząc z bardziej tradycyjnej perspektywy programowania. Istnieją dwa główne pomysły na obejście głowy:
Tak więc następujące dwa bloki skryptów wykonają dokładnie to samo:
Zmienna $ a w drugim przykładzie jest pozostawiana jako dane wyjściowe w potoku i, jak wspomniano, zwracane są wszystkie dane wyjściowe. W rzeczywistości w drugim przykładzie można całkowicie pominąć zwrot i uzyskać takie samo zachowanie (zwrot byłby sugerowany, ponieważ funkcja naturalnie kończy się i kończy).
Bez większej ilości definicji funkcji nie mogę powiedzieć, dlaczego otrzymujesz obiekt PSMethod. Domyślam się, że prawdopodobnie masz kilka linii w górę, co nie jest przechwytywane i jest umieszczane w potoku wyjściowym.
Warto również zauważyć, że prawdopodobnie nie potrzebujesz tych średników - chyba że zagnieżdżasz wiele wyrażeń w jednym wierszu.
Możesz przeczytać więcej na temat semantyki zwrotów na stronie about_Return w TechNet lub przez wywołanie
help return
polecenia z samej PowerShell.źródło
write-debug
po ustawieniu zmiennej$DebugPreference = "Continue"
zamiast"SilentlyContinue"
echo
był dla mnie problemem! Ten mały punkt boczny jest bardzo bardzo ważny. Zwracałem tablicę mieszającą, śledząc wszystko inne, ale nadal wartość zwracana nie była tym, czego się spodziewałem. Usuniętoecho
i działało jak urok.Ta część PowerShell jest prawdopodobnie najgłupszym aspektem. Wszelkie zewnętrzne dane wyjściowe generowane podczas funkcji będą zanieczyszczać wynik. Czasami nie ma żadnych danych wyjściowych, a następnie w pewnych warunkach jest jeszcze kilka nieplanowanych wyników, oprócz planowanej wartości zwrotu.
Tak więc usuwam przypisanie z oryginalnego wywołania funkcji, więc dane wyjściowe kończą się na ekranie, a następnie przechodzę przez kolejne kroki, aż coś, czego nie planowałem, wyskakuje w oknie debugera (przy użyciu programu PowerShell ISE ).
Nawet rzeczy takie jak rezerwowanie zmiennych w zewnętrznych zakresach powodują generowanie danych wyjściowych, jak
[boolean]$isEnabled
irytujące wyplucie False out, chyba że to zrobisz[boolean]$isEnabled = $false
.Kolejnym dobrym jest to,
$someCollection.Add("thing")
co wylicza liczbę nowych kolekcji.źródło
[boolean]$a
w PowerShell nie deklaruje zmiennej $ a. Możesz to potwierdzić, postępując zgodnie z tym wierszem$a.gettype()
i porównując dane wyjściowe z zadeklarowanym i zainicjowanym za pomocą łańcucha$a = [boolean]$false
.>
i<
są już używane do przekierowywania strumienia we / wy do / z plików.>=
zapisuje standardowe wyjście do pliku o nazwie=
.Dzięki PowerShell 5 mamy teraz możliwość tworzenia klas. Zmień swoją funkcję na klasę, a return zwróci tylko obiekt bezpośrednio poprzedzający ją. Oto naprawdę prosty przykład.
Gdyby to była funkcja, oczekiwany wynik byłby
ale jako klasa zwracana jest tylko liczba całkowita 808979. Klasa jest swego rodzaju gwarancją, że zwróci tylko typ deklarowany lub nieważny.
źródło
static
metody. Prowadzący do składni[test_class]::return_what()
return 808979
, funkcji lub nie.Write-Output
? Nie chodzi tu o wyjście „konsoli”, lecz o wyjście funkcji / cmdlet. Jeśli chcesz zrzucić rzeczy na konsoli istniejąWrite-Verbose
,Write-Host
aWrite-Error
funkcje, między innymi. ZasadniczoWrite-Output
jest bliższyreturn
semantyce niż procedurze wyjściowej konsoli. Nie nadużywaj tego, używajWrite-Verbose
gadatliwości, po to jest.Jako obejście zwracałem ostatni obiekt w tablicy, który otrzymałeś z funkcji ... To nie jest świetne rozwiązanie, ale jest lepsze niż nic:
Podsumowując, bardziej jednoznaczny sposób pisania tego samego może być:
źródło
$b = $b[-1]
byłby prostszym sposobem na uzyskanie ostatniego elementu lub tablicy, ale jeszcze prostszym byłoby po prostu nie generowanie wartości, których nie chcesz.write-host
aby wydrukować go bezpośrednio.Mijam prosty obiekt Hashtable z jednym elementem wynikowym, aby uniknąć szaleństwa zwrotnego, ponieważ chcę również wyświetlać dane na konsoli. Działa poprzez przekazanie przez odniesienie.
Prawdziwe przykładowe użycie można zobaczyć w moim projekcie GitHub unpackTunes .
źródło
Trudno powiedzieć bez patrzenia na kod. Upewnij się, że twoja funkcja nie zwraca więcej niż jednego obiektu i że przechwytujesz wyniki uzyskane z innych wywołań. Za co dostajesz:
W każdym razie dwie sugestie:
Rzuć obiekt na ciąg:
Lub po prostu umieść go w podwójnych cudzysłowach, takich samych jak powyżej, ale krótszych do wpisania:
źródło
"$rs"
-return
jest wymagany tylko przy wcześniejszym powrocie z funkcji. Pominięcie zwrotu jest lepszym idiomem PowerShell.Wydaje się, że opis funkcji przez Luke'a w tych scenariuszach jest słuszny. Chcę tylko zrozumieć podstawową przyczynę, a zespół produktu PowerShell zrobiłby coś z tym zachowaniem. Wydaje się być dość powszechny i kosztował mnie zbyt wiele czasu na debugowanie.
Aby obejść ten problem, używałem zmiennych globalnych zamiast zwracania i używania wartości z wywołania funkcji.
Oto kolejne pytanie dotyczące stosowania zmiennych globalnych: Ustawianie globalnej zmiennej PowerShell z funkcji, w której nazwa zmiennej globalnej jest zmienną przekazywaną do funkcji
źródło
Poniższe zwraca po prostu 4 jako odpowiedź. Po zastąpieniu dodawanych wyrażeń dla ciągów zwraca pierwszy ciąg.
Można to również zrobić dla tablicy. Poniższy przykład zwróci „Tekst 2”
Zauważ, że musisz wywołać funkcję poniżej samej funkcji. W przeciwnym razie przy pierwszym uruchomieniu zwróci błąd, że nie wie, co to jest „StartingMain”.
źródło
Istniejące odpowiedzi są poprawne, ale czasami nie zwraca się czegoś jawnie za pomocą a
Write-Output
lub areturn
, ale w wynikach funkcji jest pewna tajemnicza wartość. Może to być wynik działania wbudowanej funkcjiNew-Item
Cały ten dodatkowy szum związany z tworzeniem katalogu jest gromadzony i emitowany na wyjściu. Najłatwiejszym sposobem na złagodzenie tego jest dodanie
| Out-Null
na końcuNew-Item
instrukcji lub można przypisać wynik do zmiennej i po prostu nie używać tej zmiennej. Wyglądałoby to tak ...New-Item
jest prawdopodobnie bardziej znany z nich, ale inne obejmują wszystkieStringBuilder.Append*()
metody, a takżeSqlDataAdapter.Fill()
metodę.źródło