Carlos Quintero (Microsoft MVP) blog

Visual Studio Extensibility: macros, add-ins, SDK packages

February 2008 - Posts

Another apparently simple question that uncovers a bug introduced in VS 2005 and 2008. Fortunately the workaround is simple: 

HOWTO: Guess if a project configuration is Debug or Release from a Visual Studio add-in or macro
http://www.mztools.com/articles/2008/MZ2008005.aspx

Posted by carlosq | with no comments

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

 

Posted by carlosq | 2 comment(s)

An article for newbies, or maybe not... 

HOWTO: Use correctly the OnConnection method of a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008004.aspx

Posted by carlosq | with no comments

My latest article is about guessing the installed Visual Studio versions (2005, 2008), editions (Std, Prof, Team Edition, Team Suite), packages or service packs, either from a setup program or from a running add-in or package:

HOWTO: Detect installed Visual Studio editions, packages or service packs
http://www.mztools.com/articles/2008/MZ2008003.aspx

Posted by carlosq | with no comments