Pregunta

Estoy creando un script de Powershell para implementar algún código y parte del proceso es llamar a una herramienta de compresión de línea de comandos llamada RAR.EXE para hacer una copia de seguridad de algunas carpetas.

Estoy intentando construir dinámicamente los parámetros y luego hacer que powershell llame el comando con las variables, pero estoy teniendo problemas. No está funcionando ...

Ejecuta el siguiente script y deberías ver de qué estoy hablando. Los parámetros que se pasan como una variable están siendo destrozados. Si paso el comando completo + los parámetros en el campo obtendré el infame " no se reconoce como un cmdlet ... " mensaje.

¡Gracias por cualquier ayuda!

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
¿Fue útil?

Solución

El operador de llamada '& amp;' Es innecesario en este caso. Se utiliza para invocar un comando en un nuevo ámbito. Esto se usa normalmente para invocar un comando especificado por una cadena o scriptblock. También tiene el beneficio adicional de que todas las variables creadas en, por ejemplo, un script de PowerShell se descartan una vez que finaliza el comando y desaparece el alcance.

Sin embargo, como el cmd es un EXE, se ejecuta en un proceso completamente diferente. FWIW, obtiene un resultado similar directamente desde cmd.exe:

> cmd "/c echo foo"
foo"

Por lo tanto, la cita adicional al final es un problema de cmd.exe. Normalmente, debe mantener el comando separado de los parámetros cuando PowerShell está realizando el análisis para invocar el comando, por ejemplo,

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

La excepción notable aquí es que Invoke-Expression se comporta como " evalúa esta cadena " función. Utilícelo con cuidado, especialmente si el usuario proporciona la cadena. Tu día podría apestar si proporcionaran " ri C: \ -r " ;.

En este caso, como han sugerido otros, sacaría / c de la cadena $ param string y lo especificaría, por ejemplo:

cmd /c $param

O use Invoke-Expression pero use con cuidado. Por cierto, cuando intenta depurar problemas con el envío de argumentos a EXE desde PowerShell, consulte la utilidad echoargs en PowerShell Community Extensions ( http: / /pscx.codeplex.com ). Es muy útil:

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

Esto muestra que cmd.exe recibe " / c echo foo " como un argumento único . " / c " debe ser un argumento separado de " echo foo " (el comando a ejecutar).

Otros consejos

He tenido problemas con el & amp; llame al operador en el pasado cuando intente invocar comandos de tipo ejecutable como lo está intentando. No estoy seguro de entender por qué. Sin embargo, la expresión-invocación parece funcionar siempre en este contexto:

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

Otra forma que encontré para hacer esto fue crear una matriz de argumentos para la línea de comandos y usarla con el símbolo y & amp; operador de llamadas. Algo como esto:

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

& $exe $params;

Me ha funcionado bien.

Originalmente encontré esta técnica aquí: http://techstumbler.blogspot.com/2009/12 /windows-commands-with-arguments-in.html

Su último ejemplo si falla porque " & amp; " trata la cadena como un argumento, por lo que está buscando un programa llamado " cmd / c echo foo.exe " :)

Esto funciona:

& $cmd $params

En cuanto al tema de las comillas dobles, parece que a cmd no le gustan las citas en torno a los argumentos que pone PowerShell. Obtiene esto:

cmd "/c echo foo"

Así que creo que trata todo después de / c como el comando exacto, y así:

echo foo"

Algunos programas de la línea de comandos y el análisis funky de la línea de comandos (es por eso que PowerShell asume este trabajo para funciones y cmdlets). En el caso de cmd, sugeriría esto:

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

es un artefacto del uso de cmd / c, creo. corriendo

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

funciona bien. A menos que tenga un ejemplo de código real, es un poco difícil resolver problemas.

Los Args se tratan de manera diferente cuando están contenidos en una Cadena:

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

Los mismos resultados se producen cuando utiliza una variable para los argumentos:

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

La SOLUCIÓN es usar una matriz:

PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top