2017-07-24 3 views
5

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" 
+1

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. –

+0

Nachtrag: 'return" Continue "' nicht das gewünschte Ergebnis scheint ein Fehler zu sein, der in PowerShell v3 behoben wurde. –

Antwort

1

i Frühere erklärte, dass ich das Problem nicht hatte, aber es scheint, dass die Art, wie Sie das laufen Code Angelegenheiten, ohne ISE, Console und höhere Versionen als Powershell ausgeführt v2 das ist, was ich herausgefunden:

Ohne Problem:

  • powershell.exe -datei c: \ debugtest.ps1
  • Powershell. exe -command "c: \ debugtest.ps1".

Mit Problem:

  • powershell.exe -command c : \ Debugtest.ps1

Die Abhilfe i in diesem Fall vorgeschlagen hat Arbeit:

Sie wollen versuchen könnte (Get-GlobalDefaultWithReturn) .ToString() es in eine Zeichenfolge, wenn diese zu zwingen, ist das Problem.

Powershell Version:

Major Minor Build Revision 
----- ----- ----- -------- 
2  0  -1  -1  

Es sieht aus wie ein Fehler, aber ich etwas mehr darüber wissen noch nicht. Wahr, es ist ein wenig unvorhersehbar, aber Sie könnten die Art, wie Sie Ihren Code, z. mit FILE, wenn es eine Datei ist.

+0

Ich könnte das beschriebene Verhalten mit 'powershell -version 2' auf einem System mit installierter PowerShell v4 reproduzieren. Ich habe hier kein reines PowerShell v2-System zur Hand. Wird später am Abend verifiziert. –

+1

PowerShell v2 auf einer XP-Testbox zeigt das gleiche Verhalten wie das Ausführen einer neueren Version mit '-version 2'. –

Verwandte Themen