Оказывается, sqlcmd не возвращает коды ошибок. Я решил проанализировать выходные данные команды в поисках строки ошибки и выдать исключение, если оно было найдено. Вот фрагмент:
<mtbwa:InvokeProcess Arguments="["-b -S myServer\dev -U sa -P password -i """ + SourcesDirectory + "\DatabaseScripts\conversion.sql"""]" DisplayName="Run Conversion SQL" FileName="c:\Program Files\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe" sap:VirtualizedContainerService.HintSize="464,599" Result="[ExitCode]" WorkingDirectory="[SourcesDirectory]">
<mtbwa:InvokeProcess.ErrorDataReceived>
<ActivityAction x:TypeArguments="x:String">
<ActivityAction.Argument>
<DelegateInArgument x:TypeArguments="x:String" Name="errOutput" />
</ActivityAction.Argument>
<Sequence sap:VirtualizedContainerService.HintSize="222,208">
<sap:WorkflowViewStateService.ViewState>
<scg:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<mtbwa:WriteBuildError DisplayName="VSDBCMD Error" sap:VirtualizedContainerService.HintSize="200,22" Message="[errOutput]" />
<mtbwa:SetBuildProperties DisplayName="Set build to failed" sap:VirtualizedContainerService.HintSize="200,22" PropertiesToSet="Status" Status="[Microsoft.TeamFoundation.Build.Client.BuildStatus.Failed]" />
</Sequence>
</ActivityAction>
</mtbwa:InvokeProcess.ErrorDataReceived>
<mtbwa:InvokeProcess.OutputDataReceived>
<ActivityAction x:TypeArguments="x:String">
<ActivityAction.Argument>
<DelegateInArgument x:TypeArguments="x:String" Name="stdOutput" />
</ActivityAction.Argument>
<Sequence sap:VirtualizedContainerService.HintSize="222,237">
<sap:WorkflowViewStateService.ViewState>
<scg:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<mtbwa:WriteBuildMessage sap:VirtualizedContainerService.HintSize="200,22" Importance="[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]" Message="[stdOutput]" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" />
<If Condition="[stdOutput.Contains("The statement has been terminated.")]" sap:VirtualizedContainerService.HintSize="200,51">
<sap:WorkflowViewStateService.ViewState>
<scg:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">False</x:Boolean>
<x:Boolean x:Key="IsPinned">False</x:Boolean>
</scg:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<If.Then>
<Sequence sap:VirtualizedContainerService.HintSize="281,208">
<sap:WorkflowViewStateService.ViewState>
<scg:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<mtbwa:SetBuildProperties DisplayName="Set build to failed" sap:VirtualizedContainerService.HintSize="200,22" PropertiesToSet="Status" Status="[Microsoft.TeamFoundation.Build.Client.BuildStatus.Failed]" />
<Throw Exception="[New Exception("Conversion.sql failed")]" sap:VirtualizedContainerService.HintSize="200,22" />
</Sequence>
</If.Then>
</If>
</Sequence>
</ActivityAction>
</mtbwa:InvokeProcess.OutputDataReceived>
<sap:WorkflowViewStateService.ViewState>
<scg:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsPinned">False</x:Boolean>
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg:Dictionary>
</sap:WorkflowViewStateService.ViewState>