Domanda

Sto creando uno script Powershell per distribuire del codice e parte del processo consiste nel chiamare uno strumento di compressione da riga di comando chiamato RAR.EXE per eseguire il backup di alcune cartelle.

Sto tentando di costruire dinamicamente i parametri e quindi avere PowerShell chiamare il comando con le variabili, ma sto riscontrando problemi. Non funziona ...

Esegui il seguente script e dovresti vedere di cosa sto parlando. I parametri passati come variabili vengono modificati. Se passo l'intero comando + i parametri in ottengo che il famigerato " non viene riconosciuto come un cmdlet ... " messaggio.

Grazie per l'aiuto!

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
È stato utile?

Soluzione

L'operatore di chiamata '& amp;' non è necessario in questo caso. È usato per invocare un comando in un nuovo ambito. Questo è in genere utilizzato per invocare un comando specificato da una stringa o da uno scriptblock. Ha anche il vantaggio secondario che qualsiasi variabile creata in uno script PowerShell viene scartata al termine del comando e l'ambito scompare.

Tuttavia, poiché cmd è un EXE, viene eseguito in un processo completamente diverso. FWIW, ottieni un output simile direttamente da cmd.exe:

> cmd "/c echo foo"
foo"

Quindi la citazione extra alla fine è un problema di cmd.exe. In genere è necessario mantenere il comando separato dai parametri quando PowerShell sta eseguendo l'analisi per richiamare il comando, ad esempio

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

L'eccezione notevole qui è che Invoke-Expression si comporta come un " valuta questa stringa " funzione. Usare con cura, specialmente se l'utente fornisce la stringa. La tua giornata potrebbe fare schifo se fornissero " ri C: \ -r " ;.

In questo caso, come altri hanno suggerito, estrarrei / c dalla stringa $ param string e la specificherei ad es .:

cmd /c $param

Oppure usa Invoke-Expression ma usalo con cura. A proposito, quando si tenta di eseguire il debug di problemi con l'invio di argomenti a EXE da PowerShell, consultare l'utilità echoargs in PowerShell Community Extensions ( http: / /pscx.codeplex.com ). È molto utile:

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

Questo dimostra che cmd.exe riceve " / c echo foo " come argomento singolo . & Quot; / c " dovrebbe essere un argomento separato da " echo foo " (il comando da eseguire).

Altri suggerimenti

Ho avuto problemi con & amp; chiamare l'operatore in passato quando si tenta di invocare comandi di tipo eseguibile come si sta tentando. Non sono sicuro di capire il perché. Invoke-Expression, tuttavia, sembra sempre funzionare in questo contesto:

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

Un altro modo in cui ho scoperto di fare questo era creare un array di argomenti per la riga di comando e usarlo con l'apersand & amp; chiamare l'operatore. Qualcosa del genere:

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

& $exe $params;

Ha funzionato bene per me.

Inizialmente ho trovato questa tecnica qui: http://techstumbler.blogspot.com/2009/12 /windows-commands-with-arguments-in.html

Il tuo ultimo esempio in caso di errore perché " & amp; " considera la stringa come un argomento, quindi cerca un programma chiamato " cmd / c echo foo.exe " ;. :)

Funziona:

& $cmd $params

Per quanto riguarda il problema delle virgolette doppie, sembra che a cmd non piacciano le virgolette attorno agli argomenti che mette PowerShell. Ottiene questo:

cmd "/c echo foo"

Quindi penso che tratti tutto dopo / c come il comando esatto, quindi in questo modo:

echo foo"

Alcuni programmi da riga di comando e analisi funky della riga di comando (ecco perché PowerShell assume questo lavoro per funzioni e cmdlet). Nel caso di cmd, suggerirei questo:

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

è un artefatto dell'uso di cmd / c, credo. esecuzione

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

funziona bene. A meno che tu non abbia un esempio di codice reale, è un po 'difficile risolvere i problemi.

Gli argomenti sono trattati in modo diverso quando sono contenuti in una stringa:

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

Gli stessi risultati si verificano quando si utilizza una variabile per args:

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

La SOLUZIONE è usare un array:

PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top