2009-05-15 21 views
24

Acabo de probar esto en PowerShell v1.0. La configuración es la siguiente:¿Cómo invocar MSBuild desde PowerShell usando & operator?

Id CommandLine 
-- ----------- 
    1 $msbuild = "C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe" 
    4 $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build" 

.

Esta línea de falla con un mensaje de error poco intuitivo:

Id CommandLine 
-- ----------- 
    5 & $msbuild $a 

.

Esta línea falla porque & espera que el primer argumento sea el comando en sí.

Id CommandLine 
-- ----------- 
10 & "$msbuild $a" 

.

Esta línea funciona:

Id CommandLine 
-- ----------- 
16 cmd /c "$msbuild $a" 

.

Explique. Estoy más interesado en por qué la sintaxis & no funciona, que una solución específica de MSBuild.

+0

Sugiero usar un cmdlet auxiliar como ['Invoke-MSBuild'] (http://sedodream.com/2014/07/19/IntroducingPSBuildAnImprovedInterfaceForMsbuildexeInPowerShell.aspx) en lugar de llamar a MSBuild directamente. – orad

Respuesta

26

Los problemas que está viendo resultan de los argumentos de análisis de PowerShell. En el primer ejemplo, cuando PowerShell ve $ a, lo pasa como un solo parámetro msbuild. Podemos ver esto usando la utilidad echoargs de PSCX:.

PS> $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build" 
PS> & echoargs $a 
Arg 0 is <C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build> 

El segundo ejemplo es aún peor, porque le está diciendo PowerShell para invocar "$ $ echoargs a" como el nombre del comando y no es un nombre de comando válido.

La tercera línea funciona porque CMD.exe obtiene la forma ampliada de "$ $ echoargs a" como un solo argumento que es análisis sintácticos y ejecuta:

Usted tiene un par de opciones aquí. Primero lo hago de esta manera:

PS> & $msbuild C:\some\project\or\other\src\Solution.sln ` 
    /target:Clean /target:Build 

La otra opción es utilizar Invoke-Expresión de este modo:

PS> Invoke-Expression "$msbuild $a" 

En general trato de ser muy cuidadoso con Invoke-expresión particularmente si alguna parte de la cadena que se invoca es proporcionada por el usuario.

28

Ugh.

$collectionOfArgs = @("C:\some\project\or\other\src\Solution.sln", 
    "/target:Clean", "/target:Build") 
& $msbuild $collectionOfArgs 

Esto funciona. & toma una colección de argumentos, por lo que debe dividir las cadenas que contienen varios argumentos en una colección de argumentos de cadena.

+0

Genial ...Funcionó para mí con una lista de registro de argumentos debido al registro. –

+0

¡Gran solución! Junto con la explicación proporcionada por @ keith-hill, esto tiene mucho sentido. – simonlchilds

+0

#blessYou Esto me estaba matando. – granadaCoder

Cuestiones relacionadas