Hey Leute,
ich lese schon länger fleißig mit und versuche meine Probleme so zu lösen. Aber hier habe ich ein Problem was ich seit Tagen nicht behoben bekomme.
In unserer Firma haben wir 3 Server in einem Cluster. Darauf laufen über Hyper V etwa 50 VM's.
Der Plan ist ein Powershell Script zu schreiben was die Exportierung von Maschinen vornimmt, wenn das Backup älter als 5 Tage ist. Das war der einfach Teil. Das funktioniert auch
Um Speicherplatz sollen diese nun auch gepackt werden und zwar mit 7-zip.
Dafür sieht die Powershell ja auch einen Befehl vor. Mit
Invoke-Command
geht das auch erstaunlich einfach. Solange ich sowohl den Archiv Namen, als auch das Verzeichnis explizit angebe.
Soll heissen:
Invoke-Command -computername $computername {& 'C:\Program Files\7-Zip\7z.exe' a -t7z "C:\Archiv.7z" "C:\" -m0=LZMA2 -mx=1 -mmt4 -y}
funktioniert...
aber sobald ich Variablen einsetze:
Invoke-Command -computername $computername {& 'C:\Program Files\7-Zip\7z.exe' a -t7z $archivName $verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y}
fliegt mir das Script entweder damit um die Ohren, dass es es sich um eine
Incorrect command line
handelt, oder, dass die Variablen gleich "$null" sind...
Läuft vermutlich auf den gleichen, ersten Fehler hinaus.
Wie kann ich das Umgehen?
Ich habe schon mit single Quotes und normalen Quotes herumprobiert. Außerdem mit dem Teil:
$ExecutionContext.InvokeCommand.ExpandString($string)
Was meint ihr?
Hallo Kalkleiste,
verwende mal folgende Zeile um dir anzuschauen, was der Inhalt der Variablen bei dieser Art der Übergabe ist.
Invoke-Command {& 'echo' $archivName $verzeichnis)
Ich würde denken, dass du keine Anführungsstriche brauchst. Falls doch, kannst du mit dem Pluszeichen Strings verketten, z.B.
$verzeichnis= '"' + $verzeichnis + '"';
herbivore
Hallo herbivore,
danke für deine Antwort. Gesagt getan...beide Variablen haben einen Wert bei der Übergabe.
Das mit den Anführungszeichen habe ich berücksichtigt, leider keine Veränderung.
Incorrect Commandline.
Hallo Kalkleiste,
was passiert denn, wenn du die Variablen fest auf exakt die Werte setzt, die du sonst direkt im Befehl angegeben hast, also
$archivName = "C:\Archiv.7z"
$verzeichnis = "C:\"
Invoke-Command -computername $computername {& 'C:\Program Files\7-Zip\7z.exe' a -t7z $archivName $verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y}
bzw.
$archivName = '"C:\Archiv.7z"'
$verzeichnis = '"C:\"'
Invoke-Command -computername $computername {& 'C:\Program Files\7-Zip\7z.exe' a -t7z $archivName $verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y}
statt
Invoke-Command -computername $computername {& 'C:\Program Files\7-Zip\7z.exe' a -t7z "C:\Archiv.7z" "C:\" -m0=LZMA2 -mx=1 -mmt4 -y}
herbivore
Die Variablen sind dann zur Lauftzeit $null
wenn ich das debugge und die jeweiligen Werte abfrage sind diese aber nicht $null. Nur in diesem command...
Wird wahrscheinlich am Scope durch {} liegen.
Was passiert, wenn Du globale Variablen nutzt, also $global:archivName
beim Zugriff (nicht beim Setzen).
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo Abt,
leider auch nicht.
Incorrect commandline
$Computername = "hyper03.'Name'.local"
$verzeichnis = "D:\2012r2-vorlage"
$archivName = "D:\2012r2-vorlage.7z"
Invoke-Command -computername $Computername {& "C:\Program Files\7-Zip\7z.exe" a $global:name $global:Verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y}
Habe auch schon versucht, die Variablen Global zu deklarieren.
habe es auch Probehalber mit
$ExecutionContext.InvokeCommand.ExpandString('$global:Verzeichnis')
versucht. Aber keine Chance...Dieses kleine Biest scheint nur mit explizit angegebenen Strings arbeiten zu wollen...das kann aber nicht im Sinne des Erfinders gewesen sein 😁
Hallo Kalkleiste,
oben war die Kommandozeile:
'C:\Program Files\7-Zip\7z.exe' a -t7z $archivName $verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y
Jetzt ist sie (quasi):
"C:\Program Files\7-Zip\7z.exe" a $archivName $verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y
Da gibt es zusätzliche Unterschiede. Was ich meinte, ist exakt die nachweislich funktionierende Kommandozeile zu nehmen und dort dann sorgfältig die Variablen einzusetzen (die genau den Inhalt der vorher verwendeten Konstanten haben).
Ich wüsste keinen Grund, warum es dann nicht gehen sollte.
herbivore
Hallo,
Invoke-Command erzeugt eine neue PowerShell Session, so daß die aktuellen Variablen nicht vorhanden sind. Abhilfe schafft hier die Benutzung des ScriptBlock-Parameters, s. Using Variables in Remote PowerShell Sessions
Und hier noch ein weiterer Link dazu: How to pass arguments for remote commands
Edit: Ansonsten einfach nach "powershell invoke command pass variable" im Internet suchen, u.a. habe ich dann noch Passing local variables to a remote session in PowerShell 3.0 gefunden.
Hallo Th69,
das kann ich so pauschal nicht bestätigen. Bei meinem echo-Beispiel von oben werden die korrekten Variableninhalte ausgeben. Ich würde daher vermuten, dass die Variablen evaluiert werden, bevor die Übergabe an die neue PowerShell Session erfolgt.
herbivore
Hallo Herbivore,
es geht hier um Remote-Zugriff (d.h. mit dem Parameter -computername).
Ach mist,
herbivore hast natürlich recht. Das -t7z habe ich wohl versehntlich gelöscht... teste es gerade gegen.
Die Singlequotes scheinen grundsätzlich erstmal bei Strings keinen Unterschied zu machen, die nicht evaluiert werden müssen.
In die Variante von Th69 werde ich mich gleich reinlesen, danke aber schonmal für deine Antwort.
Sry für Doppelpost...
Leute Ihr seid der Hammer... danke für eure Hilfe...
Th69 hat den entscheidenden Hinweis gegeben...
mit
Invoke-Command -Session $session -scriptblock {param ($name, $Verzeichnis) & "C:\Program Files\7-Zip\7z.exe" a -t7z $name $Verzeichnis -m0=LZMA2 -mx=1 -mmt4 -y} -ArgumentList $name, $Verzeichnis
funktioniert es!
Vielen Dank!