2009-04-30 18 views
7

Estoy creando un script 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 realizar copias de seguridad de algunas carpetas.Powershell Comando Procesando (Pasando en Variables)

Estoy intentando construir dinámicamente los parámetros y luego hacer que powershell invoque el comando con las variables pero me está dando problemas. No funciona ...

Ejecute el siguiente script y verá de lo que estoy hablando. Los parámetros que se pasan como una variable están siendo mutilados. Si paso todos los parámetros de comando + obtengo el infame mensaje "no se reconoce como un cmdlet ...".

¡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 

Respuesta

9

El operador de llamada '&' es innecesario en este caso. Se usa para invocar un comando en un nuevo alcance. Esto se usa generalmente para invocar un comando especificado por una cadena o scriptblock. También tiene el beneficio adicional de que las variables creadas en un script de PowerShell se descartan una vez que el comando finaliza y el alcance desaparece.

Sin embargo, dado que el cmd es un EXE, se ejecuta en un proceso completamente diferente. Fwiw, se obtiene un resultado similar directamente de cmd.exe:

> cmd "/c echo foo" 
foo" 

Así que la cita extra en el final es una cuestión de cmd.exe. Normalmente, debe mantener el comando separado de los parámetros cuando PowerShell realiza el análisis para invocar el comando, p.

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 notable excepción aquí es que Invoke-expresión se comporta como una función de "evaluar esta cadena". Use con cuidado, especialmente si el usuario proporciona la cadena. Su día podría apestar si proporcionaran "ri C: \ -r".

En este caso, como otros han sugerido que tiraría de los/c de la cadena de parámetro string $ y especificar que ej .:

cmd /c $param 

O utilizar Invoke-Expresión sino que lo utiliza 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 práctico:

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

Esto demuestra que recibe cmd.exe "/ c echo foo" como un solo argumento . "/ c" debería ser un argumento separado de "echo foo" (el comando a ejecutar).

+5

Las matrices también funcionan bien para construir argumentos de línea de comando; es decir, $ cmdArgs = @ ('/ c', 'echo foo'); cmd $ cmdArgs –

0

es un artefacto de usar cmd/c, creo. ejecutando

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

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

6

He tenido problemas con el operador de llamada & en el pasado cuando intentaba invocar comandos de tipo ejecutable como lo está intentando. No estoy seguro de entender por qué. Invoke-Expresión sin embargo, siempre parece funcionar en este contexto:

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

Su último ejemplo, si no porque "&" trata la cadena como un argumento, por lo que está en busca de un programa llamado "cmd/c echo foo .exe". :)

Esto funciona:

& $cmd $params 

En cuanto a la cuestión de la doble cita, lo hace parecer que cmd no le gustan las comillas alrededor de argumentos que pone PowerShell. Se pone esto:

cmd "/c echo foo" 

así que creo que trata todo después/C como el comando exacta, por lo que de esta manera:

echo foo" 

Algunos programas de línea de comandos y el análisis moderno de la línea de comandos (es decir por qué PowerShell se hace cargo de este trabajo para funciones y cmdlets). En el caso de cmd, sugeriría esto:

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

Args son tratados de forma 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 se utiliza una variable para los args:

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

La solución es utilizar una matriz:

PS D:\> $param = @(1,2,3) 
PS D:\> echo $param 
1 
2 
3 
Cuestiones relacionadas