Upgrading automation code from VS 2003, and building Add-ins in the VS 2005 May Tech Preview

If you are trying to build Add-ins with the May Tech Preview of VS 2005 (the version we handed out at TechEd), you may run into a few bugs with the code generated by the wizard. There are a few easy workarounds to these bugs to make the wizard work again. First, open up a VS Command Prompt (Start | All Programs | Microsoft Visual Studio Whidbey | Visual Studio Tools | Visual Studio Command Prompt), then cd to the directory C:\Program Files\Common Files\Microsoft Shared\MSEnv\PublicAssemblies (assuming you installed Windows to the C drive). Next, type the command “regasm /codebase EnvDTE.dll”. This will register EnvDTE.dll as the PIA for extensibility.

 

You can now run the wizard, and the correct PIA will be found for Add-ins but you need to make one change to the code that is generated. If you generated a C# Add-in, the line

 

            object []contextGUIDS = new object[] { };

 

needs to be changed to

 

            System.Array contextGUIDS = System.Array.CreateInstance(typeof(object), 0);

The PIA that is installed was created with the /sysarray switch supplied to tlbimp, which causes any arrays to be imported as System.Array rather than object[].

 

All these bugs have been fixed since this build of VS was made. But this is a good time to discuss changes to the object model since VS 2003. First, all new interfaces can now be found in the PIA EnvDTE80.dll. We wanted to change EnvDTE.dll as little as possible, so all new interfaces, enums, etc. were placed in EnvDTE80. This means that when you want to get to any new functionality, you need to perform a cast. If you want to add a command to VS and select the type of UI for the command (which is done with the Commands2.AddNamedCommand2 method), you would use code such as this:

 

Commands2 commands = (Commands2)applicationObject.Commands;

commands.AddNamedCommand2(…)

 

And, of course, you will need to add a reference to the EnvDTE80.dll PIA.

 

We are also making a change to a few methods in the EnvDTE PIA. Around version 5 (or was it 4?) VB started using the command bar code from the Office suite of products for its command bars. Visual Studio continued with this tradition, but with VS 2005 a change is being made for performance reasons. MSO.dll (the file that contained the command bar code) is about 12MB in size. Most of the code in this DLL, while useful for Office, is not used by VS. To minimize load time and working set, the VS team forked the code tree, removed much of the unneeded code, converted it to a lib, and then linked directly to the library.

 

But this caused a new set of problems. MSO.dll contained a type library and we could not install this tlb separately from MSO.dll, otherwise we would break Office apps when we would uninstall (and, similarly, Office would break us when they would uninstall) by unregistering the tlb. So we re-GUIDed our stripped down version of MSO. Because DTE.olb referenced types inside of MSO.dll, we had to make a decision – how do we change the references inside of DTE.olb to point to the new version of MSO (internally called VSMSO)? We could re-GUID all of the types in DTE.olb, or we could do some creative, yet compatible, changes to DTE.olb. We took the compatible changes path. First, we changed the version number in the IDL file for DTE to be 8.0. Then, wherever there was a reference to one of the type in the MSO tlb, we changed it to be an IDispatch/System.Object type. This is compatible because of how the marshalling is performed in COM when the type is passed over the wire in method calls and the tlb marshaller.

 

These changes require some changes to existing code that will run against VS 2005. First, you need to change any code that calls DTE.CommandBars, Command.AddControl, Commands.RemoveCommandBar, or Commands.AddCommandBar because, rather than taking or returning a type in the Microsoft.Office.Core namespact, they now take/return an IDispatch/System.Object. Next, you need to remove the reference to EnvDTE and Microsoft.Office.Core, and replace them with references to the new, 8.0 version of EnvDTE, as well as Microsoft.VisualStudio.CommandBars. Lastly, you need to fix up any type resolution code you have. So code like this:

 

            using Microsoft.Office.Core;

 

becomes

 

            using Microsoft.VisualStudio.CommandBars;

These changes are only necessary if you are recompiling your Add-in code or trying to run a macro that uses the old types. Binary code should work just fine, but if your code is an out-of-process driver, you will need to create a binding redirect for your application. A binding redirect goes in your application’s .config file and tells the .NET Framework to load one assembly when a different one is referenced. The fragment of XML looks like this:

 

<configuration>

   <runtime>

      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

         <dependentAssembly>

            <assemblyIdentity name="EnvDTE" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />

            <bindingRedirect oldVersion="7.0.3300.0" newVersion="8.0.0.0"/>

         </dependentAssembly>

      </assemblyBinding>

   </runtime>

</configuration>

 

Lastly, in VS 2005, the file DTE.olb has been renamed to DTE80a.olb in VS 2005. This was done so we could install VS 2005 on a computer which has VS 2002/2003 without overwriting the older version.

 

Some of these changes have been made after the May Tech Preview version of VS, so if you are using that version, these changes to your code will not be necessary until you upgrade to a newer release.