Wir haben ein merkwürdiges PowerShell-Verhalten festgestellt, wenn es um Funktionsrückgabewerte geht.Unvorhersehbares Verhalten des Rückgabewerts der PowerShell-Funktion
Einige Kontext:
In unseren Skripten und Modulen, wollen wir immer die $ErrorActionPreference
und $DebugPreference
zu einem globalen Standard festlegen, der mit einer Funktion abrufbaren ist. Angenommen, wir möchten $DebugPreference
auf "Continue"
setzen, um zusätzliche Nachrichten in unserem Protokoll zu haben.
Also, wir werden so somthing zu tun:
$DebugPreference = Get-GlobalDebugPreference
Ob dies ein guter Ansatz ist, oder nicht, ist nicht von dieser Frage Teil.
Das Problem:
Auf einigen Maschinen mit verschiedenen Versionen von Powershell diese wie erwartet nicht nur nicht funktioniert. Wenn wir unsere Funktion aufgerufen, die die "Continue
“zurückgibt, $DebugPreference
tatsächlich gespeichert der richtige Wert hatte, aber wir haben keine zusätzlichen Protokollmeldungen in unserem Protokolldatei
Was fanden wir heraus.
Ob Write-Debug
funktioniert oder nicht, ist irgendwie damit verbunden, wie Sie den Wert "Continue
"von der Funktion, die unsere globalen Standardwerte verwaltet, zurückgeben.
z. Wenn die Funktion dem folgenden Beispiel ähnelt, verhält sich Write-Debug wie erwartet und gibt Debugmeldungen in PowerShell 3 aus. In PowerShell 2 ist der Wert jedoch auf "Continue
festgelegt, aber Write-Debug druckt keine zusätzlichen Nachrichten.
function Get-GlobalDebugPreference
{
return "Continue"
}
$DebugPreference = Get-GlobalDebugPreference
wenn wir jedoch nur den Wert auf die Schale fallen und lassen sie die return
Aussage, es funktioniert für alle Versionen von Powershell v2 +.
function Get-GlobalDebugPreference
{
"Continue"
}
$DebugPreference = Get-GlobalDebugPreference
es gibt mehrere Möglichkeiten, um einen Wert aus einer Funktion in Powershell zurück Für einige Möglichkeiten funktioniert es für PS Version 2, einige arbeiten mit v3. Howe Verwenden Sie Write-Output, um den Wert "Continue
zurückzugeben "funktioniert nicht bis v5.
Meiner Meinung nach sollten alle verschiedenen Ansätze gut funktionieren und sollten austauschbar sein. Dass das Verhalten für so grundlegende Dinge unterschiedlich ist, macht etwas aus und macht PowerShell etwas unberechenbar.
Ich komponierte ein kleines Skript, das die $DebugPreference
mit verschiedenen Ansätzen von Funktionsretouren setzt, die sich alle gleich verhalten sollten. Wenn Sie es mit verschiedenen PowerShell-Versionen ausführen, erhalten Sie unterschiedliche Mengen an Debug-Ausgaben. Beachten Sie, dass die Variable $DebugPreference
nach jedem Schritt den korrekten Wert und den richtigen Typ hat, aber Write-Debug funktioniert nur nach einigen von ihnen.
Kann jemand erklären, was hier vor sich geht?
es mit "powershell.exe -version 2 ...
"gibt mir diese Ausgabe:
Starting to test return values. Current DebugPreference: SilentlyContinue
1 Obtained the value with return: Continue with Type string
2 Obtained the value from shell with return after: Continue with Type string
DEBUG: 2 After Get-GlobalDefaultWithReturnAfterwards
3 Obtained the value from shell with return after: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference
4 Obtained the value without return: Continue with Type string
DEBUG: 4 After Get-GlobalDefaultWithOutReturn
5 Obtained the value with Write-Output: Continue with Type string
6 Obtained the value with Write-Output: Continue with Type System.Management.Automation.ActionPreference
7 Obtained piped value with Write-Output : Continue with Type string
8 Set the value directly: Continue with Type string
DEBUG: 8 After setting the value directly
es Laufen mit "powershell.exe -version 5 ...
" Running gibt mir diese Ausgabe:
Starting to test return values. Current DebugPreference: SilentlyContinue
1 Obtained the value with return: Continue with Type string
DEBUG: 1 After Get-GlobalDefaultWithReturn
2 Obtained the value from shell with return after: Continue with Type string
DEBUG: 2 After Get-GlobalDefaultWithReturnAfterwards
3 Obtained the value from shell with return after: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference
4 Obtained the value without return: Continue with Type string
DEBUG: 4 After Get-GlobalDefaultWithOutReturn
5 Obtained the value with Write-Output: Continue with Type string
6 Obtained the value with Write-Output: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 6 After Get-GlobalDefaultWriteOutputActionPreference
7 Obtained piped value with Write-Output : Continue with Type string
8 Set the value directly: Continue with Type string
DEBUG: 8 After setting the value directly
Das Skript:
function Get-GlobalDefaultWithReturn
{
return "Continue"
}
function Get-GlobalDefaultWithReturnAfterwards
{
"Continue"
return
}
function Get-GlobalDefaultWithReturnAfterwardsActionPreference
{
([System.Management.Automation.ActionPreference]::Continue)
return
}
function Get-GlobalDefaultWithOutReturn
{
"Continue"
}
function Get-GlobalDefaultWriteOutput
{
Write-Output "Continue"
}
function Get-GlobalDefaultWriteOutputActionPreference
{
Write-Output ([System.Management.Automation.ActionPreference]::Continue)
}
$DebugPreference = "SilentlyContinue"
Write-Host "Starting to test return values. Current DebugPreference: $DebugPreference"
$DebugPreference = Get-GlobalDefaultWithReturn
Write-Host "1 Obtained the value with return: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "1 After Get-GlobalDefaultWithReturn"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithReturnAfterwards
Write-Host "2 Obtained the value from shell with return after: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "2 After Get-GlobalDefaultWithReturnAfterwards"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithReturnAfterwardsActionPreference
Write-Host "3 Obtained the value from shell with return after: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithOutReturn
Write-Host "4 Obtained the value without return: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "4 After Get-GlobalDefaultWithOutReturn"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWriteOutput
Write-Host "5 Obtained the value with Write-Output: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "5 After Get-GlobalDefaultWriteOutput"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWriteOutputActionPreference
Write-Host "6 Obtained the value with Write-Output: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "6 After Get-GlobalDefaultWriteOutputActionPreference"
$DebugPreference = "SilentlyContinue"
Get-GlobalDefaultWriteOutput | % { $DebugPreference = $_ }
Write-Host "7 Obtained piped value with Write-Output : $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "7 After Get-GlobalDefaultWriteOutput with pipe"
$DebugPreference = "SilentlyContinue"
$DebugPreference = "Continue"
Write-Host "8 Set the value directly: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "8 After setting the value directly"
Dies sieht wie ein Fehler in der PowerShell vor v5 aus. Es sollte keinen Unterschied zwischen der Standardausgabe und der Ausgabe "Write-Output"/"echo" geben, die eine Funktion zurückgibt. Sie erhalten das korrekte Ergebnis, wenn Sie '$ global: DebugPreference' anstelle von' $ DebugPreference' ändern. –
Nachtrag: 'return" Continue "' nicht das gewünschte Ergebnis scheint ein Fehler zu sein, der in PowerShell v3 behoben wurde. –