Подтвердить что ты не робот

Код выхода PowerShell - вызов из MSBuild

Я вызываю PowerShell script из MSBuild. MSBuild способен захватить возвращаемый результат, но считает, что проект построен успешно.

Проблема заключается в том, что код выхода из PowerShell не передается команде MSBuild. Кто-то пробовал это раньше и смог отправить код выхода в 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 (конечно, это будет ошибка)

function CallFromMSBuild {

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

Когда запускается проект MSBuild, он должен был поймать проблему, и сборка должна была провалиться (вместо этого считается, что сборка выполнена успешно)

Когда я звоню из 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
4b9b3361

Ответ 1

Добавить exit $lastexitcode в test.ps1

После комментария:

Попробуйте это в test.ps1:

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

В принципе, я не думаю, что MSBuild здесь виноват.

Я пробовал твой неправильный Invoke-Command, а $lastexitcode был установлен в 0, хотя команда Invoke-Command потерпела неудачу! Вы можете проверить, работает ли это с CMD или нет, выполнив echo %errorlevel% и увидев, что вы получили 1.

Ответ 2

Этот вопрос является главным ответом на основную поисковую систему. лучший ответ - это от Джеймса Ковача (от славы пения - т.е. Он вроде FizzBinned в интеграции PowerShell и MSBuild).

В общем, в файле ps1:

  • Вставьте $ErrorActionPreference='Stop' вверху вашего script, чтобы он не был по умолчанию, т.е. SilentlyContinue (бит trap в принятом ответе имеет тот же эффект, но гораздо более косвенный и запутанный)
  • придерживаться его function exec {... (или использовать сам psake)
  • завершать вызовы внешних EXE в exec { x.exe }
  • не нужно делать какие-либо явные вещи exit ...

Обработка ошибок по умолчанию распространяет исключение как ERRORLEVEL из 1 из powershell.exe myscript.ps1, то есть в MSBuild <Exec вам не нужно делать какие-либо обманные действия, говоря им, чтобы игнорировать коды выхода и т.д. ( если вы не хотите сделать что-то условное по конкретному коду выхода, в котором вы хотите сделать IgnoreExitCode="true" и захватить его с помощью элемента <Output)

Наконец, важно понять, что в PowerShell существует $?, который является результатом последнего выражения (что не имеет значения, если вы находитесь в режиме ErrorAction='Stop'), который изменяется с каждой вещью, которую вы делаете, тогда как $LastExitCode - это код выхода DOS для последнего .exe, запускаемого в системе. Подробности здесь - обязательно прочитайте комментарии