2011-04-28 28 views
12

Invoco un script de PowerShell desde MSBuild. MSBuild puede capturar el resultado devuelto, pero cree que el proyecto se construyó con éxito.Código de salida de PowerShell - Llamar desde MSBuild

El problema es que el código de salida de PowerShell no se pasa al comando en MSBuild. ¿Alguien ha intentado esto antes y ha podido lanzar un código de salida a MSBuild?

testmsbuild.proj

<?xml version="1.0" encoding="utf-8"?> 
<Project DefaultTargets="DesktopBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup> 
    <ScriptLocation>c:\scripts\test.ps1</ScriptLocation> 
    </PropertyGroup> 

    <Target Name="AfterDropBuild" > 
     <Exec Command="powershell.exe -NoProfile -Noninteractive -command &quot;&amp; { $(ScriptLocation)%3Bexit $LASTEXITCODE }&quot; " > 
     <Output TaskParameter="ExitCode" PropertyName="ErrorCode"/> 
     </Exec> 
    </Target>  

</Project> 

test.ps1 (por supuesto esto va a error a cabo)

function CallFromMSBuild { 

    Invoke-command {Powershell.exe C:\a.ps1} -computername $computers 
} 

Cuando se activa el proyecto de MSBuild, que debería haber cogido el tema y la acumulación debe han fallado (considera la creación exitosa en su lugar)

Cuando llamo desde MSBuild

C:\Scripts>msbuild testmsbuild.proj /t:AfterDropBuild 
Microsoft (R) Build Engine Version 4.0.30319.1 
[Microsoft .NET Framework, Version 4.0.30319.225] 
Copyright (C) Microsoft Corporation 2007. All rights reserved. 

Build started 4/28/2011 2:46:29 PM. 
Project "C:\scripts\testmsbuild.proj" on node 1 (AfterDropBuild target(s)). 
AfterDropBuild: 
    powershell.exe -NoProfile -Noninteractive -command "& { c:\scripts\test.ps1;e 
    xit $LASTEXITCODE }" 
    Invoke-Command : Cannot validate argument on parameter 'ComputerName'. The argu 
    ment is null or empty. Supply an argument that is not null or empty and then tr 
    y the command again. 
    At C:\install\test.ps1:3 char:58 
    + Invoke-command {Powershell.exe C:\a.ps1} -computername <<<< $computers 
     + CategoryInfo   : InvalidData: (:) [Invoke-Command], ParameterBind 
    ingValidationException 
     + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power 
    Shell.Commands.InvokeCommandCommand 

Done Building Project "C:\scripts\testmsbuild.proj" (AfterDropBuild target(s)). 


Build succeeded. 
    0 Warning(s) 
    0 Error(s) 

Time Elapsed 00:00:01.04 
+0

relacionado: http://stackoverflow.com/questions/78069/any-good-powershell-msbuild-tasks –

Respuesta

4

Añadir exit $lastexitcode a test.ps1

Después del comentario:

probar este en test.ps1:

trap {Write-Host -foreground red $_.Exception.Message; exit 1; continue} Invoke-command {Powershell.exe C:\a.ps1} -computername $computers 

Básicamente, no creo MSBuild tiene la culpa aquí.

Probé el Invoke-Command incorrecto y el $lastexitcode se configuró en 0 aunque el comando Invoke había fallado. Puede probar si esto funciona o no desde el propio cmd al hacer echo %errorlevel% y ver que obtiene 1.

+0

¡No hay suerte! Siempre lo mismo. El código de salida es 255 cuando se ejecutó desde una ventana de powershell directamente – Sanjeev

+0

He editado mi respuesta – manojlds

+0

Gracias por la actualización. trap {} hace el truco! Ahora el MSbuild dice "Build Failed". El truco es que no muestra el $ ._ Exception.Message pensó. Todo lo que muestra es 'código' C: \ scripts \ testmsbuild.proj (12,3): error MSB3073: El comando "powershell.exe c: \ scripts \ test.ps1" salió con el código 1 'código'. La mitad de la batalla ya terminó :) – Sanjeev

15

Esta pregunta es la respuesta principal en un motor de búsqueda importante. El best answer is this de James Kovacs (de fama de psake, es decir, tiene un poco de FizzBinned en PowerShell e integración de MSBuild).

En resumen, en un archivo PS1:

  1. pegar un $ErrorActionPreference='Stop' en la parte superior de su script así que no es el predeterminado, que es SilentlyContinue (el bit trap en la respuesta aceptada tiene el mismo efecto, pero es mucho más indirecta y confusa)
  2. palo en la function exec {... (o utilizar psake sí mismo)
  3. invocaciones de envoltura de EXE externos en un exec { x.exe }
  4. no es necesario hacer ninguna expli cit exit ... materia de gestión de errores

El valor por defecto se propaga una excepción como una ERRORLEVEL de 1 de la powershell.exe myscript.ps1, es decir, en un MSBuild <Exec que no es necesario hacer ningún engaño re diciendo que hacer caso omiso de los códigos de salida, etc.(A menos que quiera hacer algo condicional en el código de salida específica, en la que usted quiere hacer IgnoreExitCode="true" y capturarlo con un elemento <Output)

Una última cosa importante entender es que dentro de PowerShell, hay una $? que es el resultado de la última expresión (que no es relevante si está en el modo ErrorAction='Stop') que cambia con cada cosa que hace, mientras que $ LastExitCode es el código de salida 'DOS' del último .exe activado en el sistema. Details here - be sure to read the comments

+0

¡Dulce! Gracias por la información. Estoy usando el código de "función Exec" mencionado en el enlace del blog para capturar el error de otro script PS (remoteinvoke.ps1) invocado en computadoras remotas desde myscript.ps1. Trap no funciona en esos casos. Escribiré una publicación detallada (y la vincularé aquí) sobre mis hallazgos y cómo la ejecutiva me ayudó a resolver los problemas: D – Sanjeev

+0

@Sanjeev: feliz de escucharlo. Ciertamente, una 'trampa' (' en error goto': P) no es mucho mejor que 'en caso de error reanudar' en la mayoría de los casos. Pero definitivamente será bueno obtener otro resumen de los bits que son realmente relevantes en lugar de acumular muchas cosas pequeñas para forzarlo a funcionar ... –

+0

@RubenBartelink de qué se trata http://geekswithblogs.net/dwdii /archive/2011/05/27/part-2-automating-a-visual-studio-build-with-powershell.aspx? – Kiquenet

Cuestiones relacionadas