PowerShell Invoke-Command Variablen Übergabe

Art Vandelay

Lieutenant
Registriert
Apr. 2020
Beiträge
774
Hallo PS Cracks,

ich habe mir für den Job ein mittlerweile recht umfangreiches Monitoring Script geschrieben, wo ich u.a. Dienste, Prozesse, Logdateien, uvm. Abfrage.
Leider leidet die Performance etwas bei der get-process Abfrage.

Hier mache ich ein
Code:
$Antwort = invoke-command -computername <SERVER> -credential <CREDENTIALS> -Scriptblock {Get-Process}
und arbeite anschließend in einer foreach Schleife alle Elemente in $Antwort einzeln ab. Das Dauert recht lange, da der Get-Process Befehl auf der <SERVER> Seite mehrere Minuten braucht bis der Befehl zum Ende kommt.

Was ich gerne tun würde, was auch deutlich schneller ist, wäre ein
Code:
$Prozessname = "Notepad"
$Antwort = invoke-command -computername <SERVER> -credential <CREDENTIALS> -Scriptblock {Get-Process | where {$_.processname -match $Prozessname}}
Jedoch wird beim invoke-command die Variable $Prozessname nicht übergeben, ich vermute, da sie auf der <SERVER> Seite nicht bekannt ist. Das Ergebnis ist die selbe vollständige Liste aller Prozesse, die Minuten zum Aufbau braucht, als würde ich keine Variable $Prozessname übergeben.
Trage ich statt der Variable $Prozessname fix einen Namen ein, kommt der Befehl in Sekunden zum Ende
Code:
$Antwort = invoke-command -computername <SERVER> -credential <CREDENTIALS> -Scriptblock {Get-Process | where {$_.processname -match "Notepad"}}
Aber das ist nicht zielführend, da ich mein Script für die Abfrage unterschiedlicher Prozesse variabel halten möchte.

Jemand eine Idee, wie ich das performanter umgesetzt bekomme?
 
Hallo,

sehr cool, ich denke das müsste es sein. Schaue ich mir die Tage noch mal an und gebe hier feedback
 
Moin,

zunächst: Get-Process sollte keine Minute(n) dauern. Hast Du das mal händisch an der lokalen Konsole am Server probiert? Natürlich dauert es länger, je mehr Prozesse es gibt. Aber es kann auch gut sein, daß da irgendwo in einer Schleife zuviel passiert.

Was die Übergabe angeht mußt man für explizite Scriptblocks (wenn die als Parameter verlangt werden wie bei Invoke-Command) seinen Scriptblock wie eine PS-Funktion aufbauen. Also mit Parameterliste.

Was da passiert ist, daß bei Invoke-Command der scriptblock - so wie man ihn halt als Parameter mitgibt -- aufs Ziel kopiert wird (1:1) und dort ausgeführt wird. Es gibt erstmal keine Interpretation. Das was in dem Scriptblock steht ist vollständig isoliert und hat mit dem Rest des Codes drumrum nichts zu tun. Insbesondere sind auch die Variablen buchstäblich ganz andere. Wie soll die Remotemaschine wissen was DEIN PC für einen Zustand hat?

Leider hat Microsoft aber für die ÜBERGABE der Parameter (Lokal zu remote) nur eine Arrayliste spezifiziert. Das im Bruch mit der restlichen PS-Konvention, über NAMEN zu binden (via Hashtable). Hier muß man deshalb AUFPASSEN, das ist DIE Situation, wo in PS tatsächlich POSITION statt NAME des Parameters relevant wird.

Als Referenz, wie man das machen kann:
PowerShell:
$Scriptblock = {
Param($Path, $Filter) # hier werden die Parameter für den scriptblock gebunden - genau wie bei einer Funktion auch
Get-ChildItem -Path $Path -Filter $Filter -Force
}

$PfadZumÜbergeben = 'C:/'
$Filter = '*.sys' # hat mit dem $Filter im Scriptblock NICHTS zu tun!

# So ist es richtig.
# $filter MUSS übergeben werden, das passiert NICHT automatisch
# Die Reihenfolge in ArgumentList muß der definierten Reihenfolge im PARAM Teil des Scriptblocks entsprechen

Invoke-Command -Computername ZIELPC -Scriptblock $Scriptblock -Argumentlist $PfadZumÜbergeben, $Filter

# SO NICHT
... -Argumentlist $filter, $Pfadzumübergeben
# Jetzt wird der lokale Wert in $Filter an den Remotewert für $Path übergeben (und umgekehrt)

# SO AUCH NICHT
... -Argumentlist $filter, $path
# Die Variable $Path existiert lokal nicht, PS steckt bei der Übergabe immer $null in den Wert
 
  • Gefällt mir
Reaktionen: Art Vandelay und PHuV
Danke euch. Das mit $using war hier wirklich schon die Lösung.
Hätte ich euch direkt per google finden können, wenn ich mal gesucht hätte. War zu einfach


Und danke natürlich für die vielen Denkanstöße die Scripte besser zu machen.

Iqra schrieb:
zunächst: Get-Process sollte keine Minute(n) dauern. Hast Du das mal händisch an der lokalen Konsole am Server probiert? Natürlich dauert es länger, je mehr Prozesse es gibt. Aber es kann auch gut sein, daß da irgendwo in einer Schleife zuviel passiert.

Ja doch, tut es. braucht manchmal mehrere Sekunden um einen Prozess der Liste hinzuzufügen. Übergebe ich | where {$_.processname -eq "prozess"} geht es blitzschnell. Kann ich aber mit leben.
 
  • Gefällt mir
Reaktionen: Gee858eeG
Zurück
Oben