samtrex
Goto Top

Unterschiede im Aufruf und Funktion von FOREACH in Powershell

Hallo Gemeinde,
ich bin vor kurzem über eine für mich seltsame Sache in einem Powershellscript gestoßen die ich nicht verstehe.
Im Beispiel befindet sich die gesuchte Gruppe immer in Domain1. Meiner Logik nach sollten also beide Funktionen - welche ja erst ein Domain1 und dann in Domain2 suchen - diese in Domain1 finden und diese mit Return zurückgeben. Nach dem Return ist die Funktion beendet:

function Test-Function-A {
    $Forest = @('domain1','domain2')  
    ForEach ($Domain in $Forest) {
        try {
            Get-ADGroup -Identity 'securitygroup' -Server $Domain | out-null  
            write-host "In $Domain" -ForegroundColor Green  
            Return $Domain
        } catch {
            write-host "Nicht in $Domain" -ForegroundColor red  
        } 
    } 
}
function Test-Function-B {
    $Forest = @('domain1','domain2')  
    $Forest | ForEach-object {
        try {
            Get-ADGroup -Identity 'securitygroup' -Server $_ | out-null  
            write-host "In $_" -ForegroundColor Green  
            Return $_
        } catch {
            write-host "Nicht in $_" -ForegroundColor red  
        } 
    } 
}

write-host "Rückgabewert Funktion A: $(Test-Function-A)"  
write-host ''  
write-host "Rückgabewert Funktion B: $(Test-Function-B)"  

Die Ausgabe sieht wie folgt aus:
In domain1
Rückgabewert Funktion A: domain1

In domain1
Nicht in Unter "DC=domain2" kann kein Objekt mit der ID "securitygroup" gefunden werden.
Rückgabewert Funktion B: domain1


Warum führt Funktion B noch die Suche in Domain 2 aus?
Für Aufklärung bin ich dankbar.

Gruß Sam

Content-ID: 306010

Url: https://administrator.de/contentid/306010

Ausgedruckt am: 22.11.2024 um 07:11 Uhr

129413
129413 02.06.2016 aktualisiert um 11:56:15 Uhr
Goto Top
Weil du erstens im catch-Teil nicht mit "Break" aus der Foreach-Schleife springst :-P sondern nur eine Ausgabe auf der Konsole machst ...
Denn dein try catch befindet sich ja innerhalb der Schleife und nicht drumherum.

Und zweitens überspringt ein "Return" mit dem foreach-cmdlet nur das aktuelle Element in der Pipeline und beendet nicht die Function ...

Und ich würde das anders machen und das Ergebnis der Suche einer Variablen zuweisen welche man dann auf Inhalt prüft, oder noch einfacher per where-object

Zu den Unterschieden der beiden Methoden siehe:
http://www.admin-source.de/BlogDeu/905/powershell-foreach-und-foreach-o ...

Gruß skybird

Zur Veranschaulichung:
# Gibt 1-10 aus ohne die 5
1..10 | %{
    if ($_ -eq 5){
        return
    }else{
        $_
    }
}

# Gibt 1-4 aus weil Schleife mit Break verlassen wird
1..10 | %{
    if ($_ -eq 5){
        break
    }else{
        $_
    }
}
SamTrex
SamTrex 02.06.2016 um 12:14:13 Uhr
Goto Top
Hi,
ich springe im Catchblock nicht mit break heraus, da ja da gar nichts passieren soll.
Es wird ja erst in Domain1 gesucht, wird die Gruppe gefunden, wird mit Return abgebrochen - soweit ich es in Deiner Antwort verstanden habe, aber nur dieser Durchlauf.
Wird in Domain1 nichts gefunden soll in Domain2 geschaut werden.
Die Seite kenne ich, werde sie mir wohl noch einmal etwas genauer zu Gemüte führen.

Schlauer bin ich allerdings noch nicht. Irgendwie scheine ich da auf dem Schlauch zu stehen. Für mich war das Return immer der "Abbruch" der Funktion mit dem Rückgabewert.
Gruß Dirk

PS: Ich habe es auch schon so probiert. Kommt aber aufs Selbe erhaus.
function Test-Function-B {
    $fReturn = $null
    $Forest = @('domain1','domain2')  
    $Forest | ForEach-object {
        try {
            Get-ADGroup -Identity 'securitygroup' -Server $_ | out-null  
            write-host "In $_" -ForegroundColor Green  
            $fReturn = $_
        } catch {
            write-host "Nicht in $_" -ForegroundColor red  
        } 
        if($fReturn -ne $null) {
              return $fReturn
        }
    } 
}
129413
129413 02.06.2016 aktualisiert um 12:29:35 Uhr
Goto Top
Schlauer bin ich allerdings noch nicht.
Dann genehmige dir erst mal einen Kaffee, siehe meine Beispiele oben ...
return verlässt in dem CMD-Let nicht die Funktion sondern überspringt nur das Element in der Schleife. Break hingegen beendet die Pipeline in der du dich ja mit foreach-objekt befindest weil es ein cmdlet ist.


Also :

Das hier ist ein Foreach via PIPELINE als CMDLet Version:
$Forest | %{}
Und das hier eben nicht
foreach($domain in $forest){
 #.....
}

Das ist der ganze Unterschied. Man kann also generell nicht sagen das return immer eine Funktion verlässt. In der Pipeline macht ein Return eben das nicht, dort benutzt du break zum verlassen, und übergibst zum Schluss noch per return das Ergebnis z.B. einer Variablen.


Im Endeffekt lässt sich das ganze aber auch auf das hier verkürzen:
function Test-Function{
    return (@('domain1','domain2') | ?{Get-ADGroup -Identity 'securitygroup' -Server $_ -EA Ignore})   
}