Visual Studio - Stopping a Multi-Project build at the first compile error

June 28, 2010

Yet another Note to Self post--

UPDATE 11/30/2014 - This functionality has been totally replaced in VS 2010 and up by one of several extensions 
(like this, or this) that will do the same thing, much more effectively...

In almost all the cases where I’m working on projects, I have multiple assemblies in the solution… In a lot of cases, I’ll make changes in one of the dependencies of my solution and when I get to a later step in the build, something else breaks.

A lot of the time, once I work my way back through the pack of build errors, I’ll find that way up my dependency tree, one of my projects had a compile error and it has trickled down through the rest of the build, causing one error after another.

A long time ago, from a source unknown to me now  I found a snippet of a Visual Studio Macro that got close to what I wanted and over the years, I’ve done some slight modifications and improvements to it and still use it.  It’s really simple, but it something that helps my workflow in small but measureable way.

So here is what I do… [after the break]

I go into the Visual Studio Macro IDE and add a new module.

 

Once you have the IDE open, I Right-click on 'MyMacros’ and add a new module

I call the module CraigsVBModule [original, huh?]. Then add the following content to my module - this module has several other items that I use, but for this example, I’ve just minimize it to what’s important.

   1: Imports System
   2: Imports EnvDTE
   3: Imports EnvDTE80
   4: Imports EnvDTE90
   5: Imports EnvDTE90a
   6: Imports EnvDTE100
   7: Imports System.Diagnostics
   8:  
   9: Public Module CraigsVSModule
  10:  
  11: '<SNIP>
  12: 'OTHER CODE
  13: '</SNIP>
  14:  
  15:     Public Sub BuildProjConfigDone( _
  16:                         ByVal Project As String, _
  17:                         ByVal ProjectConfig As String, _
  18:                         ByVal Platform As String, _
  19:                         ByVal SolutionConfig As String, _
  20:                         ByVal Success As Boolean)
  21:  
  22:         'Get the output window
  23:         Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
  24:         Dim OW As OutputWindow = CType(win.Object, OutputWindow)
  25:  
  26:         'if the build failed, then stop further builds and output error message to
  27:         'output panel
  28:         If Success = False Then
  29:             'cancel further builds
  30:             DTE.ExecuteCommand("Build.Cancel", "")
  31:             'output a more informative error message to the build pane
  32:             OW.OutputWindowPanes.Item("Build").OutputString("*********************************************************************************" + System.Environment.NewLine)
  33:             OW.OutputWindowPanes.Item("Build").OutputString("********************************  Build Stopped  ********************************" + System.Environment.NewLine + System.Environment.NewLine)
  34:             OW.OutputWindowPanes.Item("Build").OutputString("ERROR IN " & Project & System.Environment.NewLine + System.Environment.NewLine)
  35:             OW.OutputWindowPanes.Item("Build").OutputString("********************************  Build Stopped  ********************************" + System.Environment.NewLine)
  36:             OW.OutputWindowPanes.Item("Build").OutputString("*********************************************************************************" + System.Environment.NewLine)
  37:         End If
  38:     End Sub
  39:  
  40: End Module

Once that is in, I modify the Visual Studio EnvironmentEvents Module and add to that a handler for the OnBuildProjConfigDone event that calls the post build All Stop method:

   1: Private Sub BuildEvents_OnBuildProjConfigDone( _
   2:                     ByVal Project As String, _
   3:                     ByVal ProjectConfig As String, _
   4:                     ByVal Platform As String, _
   5:                     ByVal SolutionConfig As String, _
   6:                     ByVal Success As Boolean) Handles _
   7:                     BuildEvents.OnBuildProjConfigDone
   8:  
   9:     ' call out to the module when build is completed
  10:     Call CraigsVSModule.BuildProjConfigDone(Project, ProjectConfig, Platform, SolutionConfig, Success)
  11:  
  12: End Sub

Now, when I perform a full build, if any one of my projects has an error, the compile process will All Stop at the end of that project’s build and let me know exactly where the error happened.

So on those 20+ Assembly builds, I find out a lot sooner that I’ve got an error - which greatly benefits my iterative development style.

Time Elapsed 00:00:00.05
------ Build started: Project: ProcessingClasses, Configuration: Debug Any CPU ------
C:\clients\[theClient]\ProcessingClasses\Processors\ADPGenericData.cs(433,47): error CS1002: ; expected

Compile complete -- 1 errors, 0 warnings
Build started 6/28/2010 10:54:27 AM.
CoreCompile:
  C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 ...

Build FAILED.

Time Elapsed 00:00:00.56
*********************************************************************************
********************************  Build Stopped  ********************************

ERROR IN ..\ProcessingClasses\ProcessingClasses.csproj

********************************  Build Stopped  ********************************
*********************************************************************************
Build has been canceled.