Laden...

[gelöst] Powershell: Strings und Variablen

Erstellt von Kalkleiste vor 9 Jahren Letzter Beitrag vor 9 Jahren 6.447 Views
K
Kalkleiste Themenstarter:in
6 Beiträge seit 2014
vor 9 Jahren
[gelöst] Powershell: Strings und Variablen

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?

49.485 Beiträge seit 2005
vor 9 Jahren

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

K
Kalkleiste Themenstarter:in
6 Beiträge seit 2014
vor 9 Jahren

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.

49.485 Beiträge seit 2005
vor 9 Jahren

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

K
Kalkleiste Themenstarter:in
6 Beiträge seit 2014
vor 9 Jahren

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...

16.841 Beiträge seit 2008
vor 9 Jahren

Wird wahrscheinlich am Scope durch {} liegen.

Was passiert, wenn Du globale Variablen nutzt, also $global:archivName beim Zugriff (nicht beim Setzen).

K
Kalkleiste Themenstarter:in
6 Beiträge seit 2014
vor 9 Jahren

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 😁

49.485 Beiträge seit 2005
vor 9 Jahren

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

4.941 Beiträge seit 2008
vor 9 Jahren

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.

49.485 Beiträge seit 2005
vor 9 Jahren

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

4.941 Beiträge seit 2008
vor 9 Jahren

Hallo Herbivore,

es geht hier um Remote-Zugriff (d.h. mit dem Parameter -computername).

K
Kalkleiste Themenstarter:in
6 Beiträge seit 2014
vor 9 Jahren

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.

K
Kalkleiste Themenstarter:in
6 Beiträge seit 2014
vor 9 Jahren

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!