Frage

Ich bin ein Powershell-Skript erstellen einen Code und ein Teil des Prozesses zu implementieren ist ein Befehlszeilen-Kompressions-Tool aufrufen rar.exe genannt einige Ordner Back-up.

Ich bin versucht, die Parameter dynamisch zu bauen und dann Powershell Rufen Sie den Befehl mit den Variablen, aber ich bin mit in Schwierigkeiten. Es funktioniert nicht ...

Führen Sie das folgende Skript, und Sie sollten sehen, was ich rede. Die Parameter werden als Variable weitergegeben in verstümmelt werden. Wenn ich den gesamten Befehl + Parameter übergeben in ich die berüchtigte bekommen „nicht als Cmdlets erkannt ...“ angezeigt.

Vielen Dank für jede Hilfe!

echo "this should succeed"
& cmd /c echo foo

echo "why does this echo out an additional double quote?"
$param = "/c echo foo"
& cmd "$param"

echo "this does the same"
$param = "/c echo foo"
& cmd $param

echo "escaping the slash doesn't work either..."
$param = "`/c echo foo"
& cmd $param

echo "this fails, but why?"
$cmd = "cmd /c echo foo"
&$cmd
War es hilfreich?

Lösung

Der Anruf Operator '&' ist in diesem Fall nicht notwendig. Es wird verwendet, um einen Befehl in einem neuen Bereich aufzurufen. Dies wird normalerweise verwendet, um einen Befehl von einem String oder Skript angegeben aufzurufen. Es hat auch den Nebeneffekt, dass alle Variablen in etwa einem Powershell-Skript erstellt werden, nachdem der Befehl beendet verworfen und der Umfang weggeht.

Da jedoch die cmd ein EXE es in einem völlig anderen Prozess ausgeführt wird. FWIW, erhalten Sie eine ähnliche Ausgabe direkt von cmd.exe:

> cmd "/c echo foo"
foo"

So das zusätzliche Angebot am Ende ein cmd.exe Problem. Normalerweise müssen Sie den Befehl getrennt von den Parametern zu halten, wenn Powershell die Analyse macht den Befehl beispiels aufzurufen.

45> & { $foo = "foo" }
46> $foo  # Note that $foo wasn't found - it went away with the scope
47> . { $foo = "foo" } # dotting executes in the current scope
48> $foo 
foo

Eine bemerkenswerte Ausnahme ist hier, dass Invoke-Expression wie eine „werten diese Zeichenfolge“ Funktion verhält. Verwenden Sie vorsichtig, insbesondere , wenn der Benutzer die Zeichenfolge zur Verfügung stellt. Ihr Tag könnte saugen, wenn sie zur Verfügung gestellt "ri C: \ -r".

In diesem Fall, wie andere vorgeschlagen haben würde ich die / c aus der Zeichenfolge $ param Zeichenfolge ziehen, und geben Sie es z.

cmd /c $param

oder Invoke-Expression verwenden, aber mit Vorsicht verwendet werden. BTW, wenn Sie debuggen Probleme versuchen, mit Argumenten zu EXE von Powershell zu senden, überprüfen Sie die EchoArgs Dienstprogramm in Powershell Community-Erweiterungen aus ( http: / /pscx.codeplex.com ). Es ist sehr praktisch:

49> $param = "/c echo foo"
50> echoargs $param
Arg 0 is </c echo foo>

Dies zeigt, dass cmd.exe "/ c echo foo" als Single Argument erhält. "/ C" sollte ein separates Argument von "echo foo" (der Befehl auszuführen).

Andere Tipps

Ich habe Probleme mit dem hat und Betreiber in der Vergangenheit nennen, wenn sie versuchen ausführbare -Art-Befehle aufzurufen, wie Sie wollen. Nicht sicher, ob ich verstehen, warum. jedoch Invoke-Expression, immer scheint in diesem Zusammenhang zu arbeiten:

PS C:\> $cmd = "cmd /c echo foo"
PS C:\> Invoke-expression $cmd
foo

Eine andere Art, wie ich dies zu tun fand, war eine Reihe von Argumenten für die Kommandozeile zu erstellen und verwenden, die mit dem apersand & rufen Betreiber. So etwas wie folgt aus:

$exe = "cmd";
[Array]$params = "/c", "echo", "foo";

& $exe $params;

Es funktionierte gut für mich.

Ich fand ursprünglich diese Technik hier: http://techstumbler.blogspot.com/2009/12 /windows-commands-with-arguments-in.html

Ihr letztes Beispiel wenn es nicht gelingt, weil „&“ die Zeichenfolge als ein Argument behandelt, so ist es für ein Programm namens „cmd / c echo foo.exe“ suchen. :)

Das funktioniert:

& $cmd $params

Wie für die doppelte Anführungszeichen Problem, nicht wahr, dass cmd scheint es nicht wie die Anführungszeichen um Argumente, die Powershell stellt. Es wird so aus:

cmd "/c echo foo"

Also ich denke, es behandelt alles nach / c wie den genauen Befehl, so etwa so:

echo foo"

Einige Kommandozeilenprogramme und funky Parsen der Kommandozeile (das ist, warum Powershell über diesen Job für Funktionen und Cmdlets nimmt). Im Fall von cmd, würde ich vorschlagen, diese:

$param = "echo foo"
& cmd /c $param

es ist ein Artefakt mit cmd / c, denke ich. Laufen

$param = "echo foo"
cmd /c $param

funktioniert. Es sei denn, Sie ein echtes Codebeispiel haben, es ist ein bisschen schwer zu Ärger zu schießen.

Args werden anders behandelt, wenn sie in einem String enthalten sind:

PS D:\> echo "1 2 3"
1 2 3
PS D:\> echo 1 2 3
1
2
3

Die gleichen Ergebnisse auftreten, wenn Sie eine Variable für die args verwenden:

PS D:\> $param = "1 2 3"
PS D:\> echo $param
1 2 3

Die Lösung ist ein Array zu verwenden:

PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top