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

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

  1. Here is another solution, by temporarily setting the OnlySaveStartupProjectsAndDependencies to false:

    Sub BuildSolution()
    Dim props As Properties = DTE.Properties(“Environment”, “ProjectsAndSolution”)
    Dim prop As [Property] = props.Item(“OnlySaveStartupProjectsAndDependencies”)
    Dim oldValue = prop.Value
    prop.Value = False
    Try
    DTE.Solution.SolutionBuild.Build()
    Finally
    prop.Value = oldValue
    End Try
    End Sub

Comments are closed.