IT-Profis arbeiten selten nur auf unserem lokalen Computer. Mit dem PowerShell Invoke-Command Cmdlet müssen wir nicht! Mit diesem Cmdlet können wir nahtlos Code schreiben, als ob wir auf unserem lokalen Computer arbeiten würden.
Mithilfe der PowerShell-Remoting-Funktion ist das Cmdlet Invoke-Command
ein häufig verwendetes PowerShell-Cmdlet, mit dem der Benutzer Code innerhalb einer PSSession ausführen kann., Diese PSSession kann entweder eine sein, die zuvor mit dem Cmdlet New-PSSession
erstellt wurde, oder sie kann schnell eine temporäre Sitzung erstellen und abreißen.
Related: PowerShell Remoting: The Ultimate Guide
Denken Sie an Invoke-Command als PowerShell psexec. Obwohl sie unterschiedlich umgesetzt werden, ist das Konzept das gleiche. Nehmen Sie einen Bitcode oder Befehl und führen Sie ihn „lokal“ auf dem Remotecomputer aus.
Damit Invoke-Command
funktioniert, muss PowerShell Remoting aktiviert und auf dem Remote-Computer verfügbar sein., Standardmäßig ist es auf allen Windows Server 2012 R2-oder neueren Computern zusammen mit den entsprechenden Firewall-Ausnahmen aktiviert. Wenn Sie unglücklich genug sind, immer noch Server 2008-Maschinen zu haben, gibt es mehrere Möglichkeiten, Remoting einzurichten, aber eine einfache Möglichkeit besteht darin, winrm quickconfig
oder Enable-PSRemoting
auf dem Remote-Computer auszuführen.
Um zu demonstrieren, wie Invoke-Command mit einem „Ad-hoc-Befehl“ funktioniert, dh einem Befehl, für den keine neue PSSession erstellt werden muss, nehmen wir an, Sie haben einen Remote-Computer mit Windows Server 2012 R2 oder höher Domain-joined., Bei der Arbeit an Arbeitsgruppencomputern wird es etwas chaotisch. Ich öffne meine PowerShell-Konsole, gebe Invoke-Command
ein und drücke die Eingabetaste.
Ich werde sofort gebeten, einen Scriptblock bereitzustellen. Der Scriptblock ist der Code, den wir auf dem Remote-Computer ausführen werden.
Damit wir nachweisen können, dass der Code im Scriptblock auf dem Remotecomputer ausgeführt wird, führen wir einfach den Befehl hostname
aus. Dieser Befehl gibt den Hostnamen des Computers zurück, auf dem er ausgeführt wird., Das Ausführen von hostname
auf meinem lokalen Computer ergibt einen Namen.
PS> hostnameMACWINVM
Übergeben wir nun einen Scriptblock mit demselben Code innerhalb eines Scriptblocks an Invoke-Command
. Bevor wir das tun, vergessen wir einen erforderlichen Parameter: ComputerName
. Wir müssen Invoke-Command
mitteilen, auf welchem Remote-Computer dieser Befehl ausgeführt werden soll.
PS> Invoke-Command -ScriptBlock { hostname } -ComputerName WEBSRV1 WEBSRV1
Beachten Sie, dass die Ausgabe von hostname
jetzt der Name des Remotecomputers ist WEBSRV1
. Sie haben Code auf WEBSRV1 ausgeführt., Das Ausführen von einfachem Code innerhalb eines Scriptblocks und das Übergeben an einen einzelnen Remote-Computer ist die einfachste Anwendung von Invoke-Command
aber es kann noch viel mehr.
Inhaltsverzeichnis
Übergeben lokaler Variablen an Remote-Scriptblocks
Sie haben keine einzige Aufrufbefehlsreferenz innerhalb eines Skripts. Ihr Skript wird wahrscheinlich Dutzende von Zeilen lang sein, Variablen an bestimmten Stellen definiert, Funktionen in Modulen definiert und so weiter., Auch wenn es unschuldig erscheinen mag, nur Code in ein paar geschweifte Klammern einzuschließen, ändern Sie tatsächlich den gesamten Bereich, in dem Code ausgeführt wird. Schließlich senden Sie diesen Code an einen Remote-Computer. Dieser Remotecomputer hat keine Ahnung vom gesamten lokalen Code auf Ihrem Computer, außer dem, was sich im Scriptblock befindet.
Zum Beispiel haben Sie vielleicht eine Funktion mit Computernamen und einem Dateipfadparameter. Diese Funktion dient dazu, einige Software-Installer auf dem Remote-Computer auszuführen., Sie können den Computernamen und den „lokalen“ Dateipfad an das Installationsprogramm übergeben, das sich bereits auf dem Remotecomputer befindet.
Die folgende Funktion scheint vernünftig zu sein, oder? Lass es uns laufen.
Es schlägt mit einer obskuren Fehlermeldung fehl, da ich den Ampersand-Operator verwende. Der Code war nicht falsch, aber er ist fehlgeschlagen, weil $InstallerFilePath
leer war, obwohl Sie einen Wert mit dem Funktionsparameter übergeben haben. Wir können dies testen, indem wir das kaufmännische und durch Write-Host
.,
PS> Install-Stuff -ComputerName websrv1 -InstallerFilePath 'C:\install.exe'Installer path is:PS>
Beachten Sie, dass der Wert von $InstallerFilePath
nichts. Die Variable wurde nicht erweitert, da sie nicht an den Remote-Computer übergeben wurde. Um lokal definierte Variablen an den Remote-Scriptblock zu übergeben, haben wir zwei Möglichkeiten: Wir können den Variablennamen mit $using:
innerhalb des Scriptblocks Vorwort oder wir können Invoke-Command
parameter ArgumentList
. Schauen wir uns beide an.,
Der Parameter ArgumentList
Eine Möglichkeit, lokale Variablen an einen entfernten Skriptblock zu übergeben, besteht darin, den Parameter Invoke-Command
ArgumentList
zu verwenden. Mit diesem Parameter können Sie lokale Variablen an den Parameter übergeben und lokale Variablenreferenzen im Scriptblock durch Platzhalter ersetzen.
Die Übergabe der lokalen Variablen an den Parameter ArgumentList
ist einfach.
Invoke-Command -ComputerName WEBSRV1 -ScriptBlock { & $InstallerFilePath } -ArgumentList $InstallerFilePath
Der Parameter ArgumentList
ist eine Objektsammlung. Mit Objektsammlungen können Sie ein oder mehrere Objekte gleichzeitig übergeben., In diesem Fall übergebe ich nur einen.
Wenn das Cmdlet Invoke-Command ausgeführt wird, nimmt das Cmdlet Invoke-Command diese Sammlung und injiziert sie dann in den Scriptblock, der sie im Wesentlichen in ein Array namens $args
. Denken Sie daran, dass $args -eq ArgumentList
. An diesem Punkt würden Sie auf jeden Index der Sammlung verweisen, genau wie auf ein Array. In unserem Fall hatten wir nur ein Element in der Sammlung ($InstallerFilePath
), das in $args
übersetzt wurde der erste Index in dieser Sammlung., Wenn Sie jedoch mehr hätten, würden Sie mit ihnen verweisen $args
, $args
und so weiter.
Wenn Sie Scriptblock-Variablen bessere Variablennamen zuweisen möchten, können Sie dem Scriptblock auch Parameter wie eine Funktion hinzufügen. Schließlich ist ein Scriptblock nur eine anonyme Funktion. Um Scriptblock-Parameter zu erstellen, erstellen Sie einen Param-Block mit dem Namen des Parameters. Einmal erstellt, dann verweisen Sie auf diesen Parameter im Scriptblock wie unten.,
Invoke-Command -ComputerName WEBSRV1 -ScriptBlock { param($foo) & $foo } -ArgumentList $InstallerFilePath
In diesem Fall werden die Elemente in der Sammlung ArgumentList
den definierten Parametern in der Reihenfolge“ zugeordnet“. Die Parameternamen spielen keine Rolle; Es ist die Reihenfolge, die wichtig ist. Invoke-Command
nimmt das erste Element in der Sammlung ArgumentList
, sucht nach dem ersten Parameter und ordnet diese Werte zu, macht dasselbe für den zweiten, den dritten und so weiter.
Das Konstrukt $Using
Das Konstrukt $using
ist eine weitere beliebte Methode, um lokale Variablen an einen Remote-Skriptblock zu übergeben., Mit diesem Konstrukt können Sie die vorhandenen lokalen Variablen wiederverwenden, dem Variablennamen jedoch einfach $using:
voranstellen. Sie müssen sich keine Sorgen über eine $args
– Sammlung oder das Hinzufügen eines Parameterblocks machen.
Invoke-Command -ComputerName WEBSRV1 -ScriptBlock { & $using:InstallerFilePath }
Das PowerShell $using
– Konstrukt ist viel einfacher, aber wenn Sie jemals in Lernpester geraten, werden Sie sehen, dass ArgumentList
Ihr Freund sein wird.,
Invoke-Command und New-PSSession
Technisch gesehen geht es in diesem Beitrag nur um Invoke-Command, aber um seine Nützlichkeit zu demonstrieren, müssen wir auch kurz auf den Befehl New-PSSession
. Erinnern Sie sich früher, dass ich erwähnt habe Invoke-Command
kann“ Ad-hoc “ – Befehle verwenden oder vorhandene Sitzungen verwenden.
In diesem Beitrag haben wir gerade „Ad-hoc“ – Befehle auf Remote-Computern ausgeführt. Wir haben eine neue Sitzung gestartet, Code ausgeführt und abgerissen., Dies ist in Ordnung für einmalige Situationen, aber nicht so sehr für eine Zeit, in der Sie Dutzende von Befehlen auf demselben Computer ausführen. In diesem Fall ist es besser, eine vorhandene PSSession wiederzuverwenden,indem Sie im Voraus eine mit New-PSSession
.
Bevor Sie Befehle ausführen, müssen Sie zunächst eine PSSession mit New-PSSession
erstellen. Wir können dies tun, indem wir einfach $session = New-PSSession -ComputerName WEBSRV1
. Dadurch wird eine Remote-Sitzung auf dem Server sowie ein Verweis auf diese Sitzung auf meinem lokalen Computer erstellt., An diesem Punkt kann ich meine ComputerName
Referenzen durch Session
ersetzen und Session
auf meine gespeicherte $session
Variable verweisen.
Invoke-Command -Session $session -ScriptBlock { & $using:InstallerFilePath }
Wenn Sie ausgeführt werden, werden Sie feststellen, dass die Leistung schneller ist, da die Sitzung bereits erstellt wurde. Nach Abschluss ist es jedoch wichtig, die offene Sitzung mit Remove-PSSession
zu entfernen.
Zusammenfassung
Das PowerShell-Cmdlet Invoke-Command ist eines der gebräuchlichsten und leistungsstärksten Cmdlets. Es ist eine, die ich persönlich am meisten von fast allen benutze., Die Benutzerfreundlichkeit und die Möglichkeit, Code auf Remote-Computern auszuführen, sind äußerst leistungsstark und ein Befehl, den ich empfehle, von oben nach unten zu lernen!