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
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