MZ-Tools Articles Series: BUG: SolutionBuild.Build method builds only one project in Visual Studio add-ins or macros

I thought I already posted a blog entry about my last article:

BUG: SolutionBuild.Build method builds only one project in Visual Studio add-ins or macros
http://www.mztools.com/articles/2008/MZ2008002.aspx

but it seems that no, so there it is. Today I was adding another post with more info:

Someone posted a question about this in the MSDN forums and I suggested to try the interfaces of the SDK (such as IVsSolutionBuildManager) instead of the automation model (EnvDTE). I have had a little time to actually try it and, alas, it doesn’t work too, so it seems that the bug happens in the service and not in the automation model. If you load the add-in for a solution with two projects, you will notice that only the startup project is actually built, the same problem that using the automation model. If this bug is important for you, vote for it on the Microsoft Connect web site:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=320688

As you will notice, the bug was opened three times, somehow MS failed to reproduce it twice and close it, and when finally they reproduced it their explanation is that if you have the Tools, Options, Projects and Solutions, Build and Run, “Only build startup projects and dependencies on Run” option set to True, then SolutionBuild should honor it. This is absurd, because nobody is talking about “Run” here, we are talking about “Build”, which is a different thing. If I ask programmatically SolutionBuild.Build, I would expect the whole solution to be built…

The workaround is to iterate all the projectsof the solution (taking into account the dependencies, I guess) and build each one individually, this is insane…

Below is the code using the SDK just in case you are interested.

Imports System
Imports Microsoft.VisualStudio.CommandBars
Imports Extensibility
Imports EnvDTE
Imports EnvDTE80
Imports System.Runtime.InteropServices
Imports Microsoft.VisualStudio.Shell.Interop

Public Class Connect
Implements IDTExtensibility2

<ComVisible(True), ComImport(), Guid(“6D5140C1-7436-11CE-8034-00AA006009FA”), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Friend Interface IServiceProvider
<PreserveSig()> _
Function QueryService(<InAttribute()> ByRef guidService As Guid, _
<InAttribute()> ByRef riid As Guid, <OutAttribute()> ByRef ppvObject As IntPtr) As Integer
End Interface

Private m_objDTE2 As DTE2

Public Sub OnConnection(ByVal application As Object, ByVal connectMode As ext_ConnectMode, ByVal addInInst As Object, ByRef custom As Array) Implements IDTExtensibility2.OnConnection

m_objDTE2 = CType(application, DTE2)

Select Case connectMode
Case ext_ConnectMode.ext_cm_Startup
‘ OnStartupComplete will be called automatically
Case ext_ConnectMode.ext_cm_AfterStartup
OnStartupComplete(Nothing)
End Select

End Sub

Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete
BuildSolution()
End Sub

Private Sub BuildSolution()

Dim objIVsSolutionBuildManager As IVsSolutionBuildManager
Dim iResult As Integer

objIVsSolutionBuildManager = DirectCast(GetService(m_objDTE2, GetType(IVsSolutionBuildManager)), IVsSolutionBuildManager)

iResult = objIVsSolutionBuildManager.StartSimpleUpdateSolutionConfiguration(CType(VSSOLNBUILDUPDATEFLAGS.SBF_OPERATION_BUILD Or VSSOLNBUILDUPDATEFLAGS.SBF_OPERATION_FORCE_UPDATE, UInt32), 0, 0)

End Sub

Friend Function GetService(ByVal serviceProvider As Object, ByVal type As System.Type) As Object
Return GetService(serviceProvider, type.GUID)
End Function

Friend Function GetService(ByVal serviceProvider As Object, ByVal guid As System.Guid) As Object

Dim objService As Object = Nothing
Dim objIServiceProvider As IServiceProvider
Dim objIntPtr As IntPtr
Dim hr As Integer
Dim objSIDGuid As Guid
Dim objIIDGuid As Guid

objSIDGuid = guid
objIIDGuid = objSIDGuid
objIServiceProvider = CType(serviceProvider, IServiceProvider)
hr = objIServiceProvider.QueryService(objSIDGuid, objIIDGuid, objIntPtr)

If hr <> 0 Then
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr)
ElseIf Not objIntPtr.Equals(IntPtr.Zero) Then
objService = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(objIntPtr)
System.Runtime.InteropServices.Marshal.Release(objIntPtr)
End If

Return objService

End Function

Public Sub OnDisconnection(ByVal disconnectMode As ext_DisconnectMode, ByRef custom As Array) Implements IDTExtensibility2.OnDisconnection
End Sub

Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
End Sub

Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
End Sub

End Class