Pergunta

Estou criando um script PowerShell para implantar um código e parte do processo é chamar uma ferramenta de compressão de linha de comando chamado rar.exe para back-up algumas pastas.

Eu estou tentando criar dinamicamente os parâmetros e, em seguida, powershell ter chamar o comando com as variáveis, mas eu estou correndo em problemas. Ele não está funcionando ...

Execute o seguinte script e você deve ver o que estou falando. Os parâmetros a ser transmitida como uma variável estão a ser deturpados. Se eu passar toda a parâmetros de comando + na recebo o infame "não é reconhecido como um cmdlet ..." mensagem.

Obrigado por qualquer ajuda!

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
Foi útil?

Solução

O operador de call 'e' é desnecessário neste caso. Ele é usado para invocar um comando em um novo escopo. Isso normalmente é usado para invocar um comando especificado por uma corda ou scriptblock. Ele também tem o benefício lateral que quaisquer variáveis ??criadas em dizer um script PowerShell são descartados após o comando acabamentos eo alcance vai embora.

No entanto, desde o cmd é um EXE que executa em um processo completamente diferente. FWIW, você recebe saída semelhante diretamente de cmd.exe:

> cmd "/c echo foo"
foo"

Assim, a citação extra no final é uma questão cmd.exe. Normalmente, você precisa manter o comando separado dos parâmetros quando PowerShell está fazendo a análise para invocar o comando por exemplo.

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

A exceção notável aqui é que se comporta Invoke-expressão como uma função de "avaliar essa string". Use com cuidado, especialmente se o usuário fornece a string. Seu dia pode chupar se eles forneceram "ri C: \ r".

Neste caso, como outros já sugeriu que eu iria puxar a / c fora da corda param string $ e especificá-lo por exemplo:.

cmd /c $param

Ou usar Invoke-Expression, mas use com cuidado. BTW, quando você está tentando depurar problemas com o envio de argumentos para EXE do PowerShell, visite o utilitário echoargs em PowerShell Community Extensions ( http: / /pscx.codeplex.com ). É muito útil:

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

Isso mostra que cmd.exe recebe "/ c echo foo" como um única argumento. "/ C" deve ser um argumento separado do "echo foo" (o comando para executar).

Outras dicas

Eu tive problemas com o operador & chamada no passado ao tentar chamar comandos tipo executáveis ??como você está tentando. Não tenho certeza eu entendo o porquê. Invoke-Expression no entanto, parece estar sempre a trabalhar neste contexto:

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

Uma outra maneira que eu encontrei para fazer isso era para criar uma matriz de argumentos para a linha de comando e uso isso com o apersand & chamada do operador. Algo parecido com isto:

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

& $exe $params;

Tem funcionado bem para mim.

Eu originalmente encontrado esta técnica aqui: http://techstumbler.blogspot.com/2009/12 /windows-commands-with-arguments-in.html

Seu último exemplo, se falhar porque "e" trata a cadeia como um argumento, por isso está à procura de um programa chamado "cmd / c echo foo.exe". :)

Isso funciona:

& $cmd $params

Quanto à questão de aspas duplas, ele faz parecer que cmd não gosta as aspas em torno argumentos que coloca PowerShell. Ela recebe a seguinte:

cmd "/c echo foo"

Então eu acho que ele trata tudo após / c que o comando exato, então assim:

echo foo"

Alguns programas de linha de comando e de análise funk da linha de comando (por isso PowerShell assume este trabalho para funções e cmdlets). No caso de cmd, gostaria de sugerir o seguinte:

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

é um artefato de usar cmd / c, eu acho. correndo

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

funciona bem. A menos que você tem um exemplo de código real, é um pouco difícil de atirar problemas.

Args são tratados de forma diferente quando eles estão contidos em uma string:

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

Os mesmos resultados ocorrem quando você usa uma variável para os argumentos:

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

A solução é usar um array:

PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top