Category Archives: MZ-Tools Articles Series

MZ-Tools Articles Series: HOWTO: Create a setup for a Visual Studio 2005 / 2008 add-in using Inno Setup

This is another of those articles long overdue that I kept in a list and that I wanted to write. Back in 2004 I finished the first commercial version of my MZ-Tools add-in for .NET and despite my hate for setups (I much prefer XCOPY deployment to be confident that my computer remains uncorrupted) I knew I had to create one because my customers would expect it (the free versions of MZ-Tools for VB6/VBA/VB5 didn’t have a setup until many years after its origin back in the year 2000) and alas, add-ins in VS.NET are much more complicated to deploy (you needed an ActiveX/COM shim control to create toolwindows in VS.NET 2002/2003, for example).

So, my first choice was, of course, the MSI-based setup project that VS.NET 2002 created for each add-in project. The result was that, if I already hated setups, I hate MSI-based setups even more since then. I found several problems:

  • The setup used a progress bar that when reached 100%, it started again for a second phase. Being a perfectionist, I prefer a single pass from 0% to 100%, and if for some reason the setup can’t go from 0% to 50% in the first phase and from 50% to 100% in the second phase, I much prefer no progressbar at all (alas, my current uninstaller has the same problem that I have been unable to solve yet although I am close). Anyway, this is a minor detail.
  • For some customizations you couldn’t use the setup project properties, but you needed a tool named Orca MSI editor, or something like that.
  • If you want a multilanguage setup (not a different setup for each language) I think that it was not possible.
  • I needed slightly different setups for the trial version and the full version, and the setup project didn’t allow that easily.
  • And finally there was a nasty bug (or “by design” issue) that I documented and reported to Microsoft: BUG: Visual Studio .NET Setup Projects Execute Custom Action of Previous Version when Upgrading.

Finally I gave up MSI and searching alternatives, I found Inno Setup, a free script based setup. It allows multilanguage setups in a single .exe, it has preprocessor capabilities (conditional compilation that I use for the Trial/Full version) and despite being script-based it has a companion ISTool to create the setup more user-friendly. Furthermore it has great forums, 3rd party tools and web sites devoted to provide useful scripts for some tasks. And guess what? Its progress bar goes a single time from 0% to 100% and very fast :-).

So, despite being now a Microsoft MVP and being aware that Microsoft greatly recommends MSI for setups due to its transaction capabilities, if you need a setup for an add-in (not for a VS SDK package) which uses XML registration and no COM registration is involved, you are quite safe using a non MSI-based setup (FWIW my add-in uses COM registration for historical reasons and I have had no problems with my customers using Inno Setup).

Since InnoSetup is script-based and it uses Pascal as language for the custom code, I wrote a ready-to-use Inno Setup script that you can customize easily and use. The details are in the following article:

HOWTO: Create a setup for a Visual Studio 2005 / 2008 add-in using Inno Setup
http://www.mztools.com/articles/2008/MZ2008010.aspx

MZ-Tools articles series: HOWTO: Removing commands and UI elements during Visual Studio .NET add-in uninstallation (updated)

I have updated a quite old but useful article (Feb 2005) to document the new /ResetAddin command-line flag of Visual Studio 2005/2008 and how to do it correctly:

HOWTO: Removing commands and UI elements during Visual Studio .NET add-in uninstallation
http://www.mztools.com/articles/2005/MZ2005002.aspx

It is important to note that the /ResetAddin command-line flag will remove permanent controls but not permanent commandbars (another reason to not use them). 

MZ-Tools Articles Series: HOWTO: Get the text editor font and colors information in a Visual Studio add-in

Although I wrote long time ago an article about EnvDTE.DTE.Properties, it was not until this week that I needed to retrieve font and color information of the text editor of Visual Studio. Basically I am changing the code template editor of my MZ-Tools add-in from black and white to colorized text using a RichTextBox, resembling as much as possible the code editor of VS without using more complex 3rd party products (such as Activepro Syntaxt Editor, which seems excellent) or trying to host the Visual Studio code editor inside a Windows Form.

Here is a new article about this subject and some things that I have encountered.

HOWTO: Get the text editor font and colors information in a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008008.aspx

BTW, notice that VS 2005 has a bug (fixed in VS 2008) and the “Comment” foreground color is not returned correctly (although the VS code editor colorizes perfectly). You may want to use the XML Comment or CSS Comment foreground color in this case.

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

MZ-Tools Articles Series: HOWTO: Detect installed Visual Studio editions, packages or service packs

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

MZ-Tools Articles Series: PRB: PEVerify.exe causes problem with EnvDTE.dll verifying Visual Studio 2005 add-ins

It happens that VSLangProj.dll references EnvDTE.dll version 7.0.3300.0 while Visual Studio 2005 add-ins use EnvDTE.dll version 8.0.0.0, so this causes problems verifying assemblies with peverify.exe. See here how to solve this problem:

PRB: PEVerify.exe causes problem with EnvDTE.dll verifying Visual Studio 2005 add-ins
http://www.mztools.com/Articles/2007/MZ2007032.aspx