Share via


COM Shim Wizards for VS 2010

About a month ago I wrote a post on compiling the COM shim for 64-bit where I was hoping to have a version of COM Shim Wizards working with Visual Studio 2010. Today I am announcing the coming out of COM Shim Wizards for VS 2010 … I am calling it "coming out" and not a binding word "release" simply because it is not a release. All I am going to do is attach an MSI package to this blog post and explain what you will get when you install this file on your machine. I am not promising any support - although I am not denying that, as long as I am interested in this area, I will try to fix issues if they are reported in the comments to this post. Again, this is not an official release from Microsoft but just something I have done in my spare time because long time ago I was fortunate enough to work with Andrew Whitechapel and Siew Moi Khor to start it all.

For the information on why it is important to isolate shared add-ins using a COM shim please refer to this article. You can find here all the details why and how you need to digitally sign the shim and also how shim provides certain level of isolation for the managed add-in by placing it in a separate AppDomain.

There is a separate article explaining the architecture of the shimmed solution and also shows how to use the COM Shim Wizards to easily create a shim around your existing managed add-in.

So, let's start enumerating the changes the COM Shim Wizards went through when compared to the one we had in the last release:

  • The MSI package attached to this post will install project templates for Visual Studio 2010 only. Notice that VS 2010 should be installed on the machine first. There is no option to install to VS 2008 / VS 2005.
  • Only the project template for AddIn Shim is now installed. Shims for RealTimeData and SmartTags were dropped – neither I or Andrew saw a lot of demand for these and we decided to not invest the required time into the required support.
  • When harvesting information from the assembly we have a new data field called "Image Version". This data is important. In particular if the image's version v2.0.50727 – the generated shim will use CLR 1.0 hosting interfaces, if the image's version is different – the generated shim will use CLR 4.0 hosting interfaces. I explain the nuances about hosting interfaces below.
  • Fixed the bugs in ManagedAggregator.cs and CLRLoader.cpp that could cause the host application to not property shutdown (see the comment in the MSDN article regarding these bugs)
  • As in the last release, the created shim is a 32-bit native DLL. Please follow the steps outlined in the "Taking COM Shim Wizards to 64-bit" to compile a 64-bit version

CLR Hosting Interfaces

The way we host CLR is the only significant change in the code that is being generated by the AddIn Shim template. In the previous version of the shim we used what is called CLR 1.0 Hosting Interfaces – i.e. these are the hosting interfaces that were available in the initial release of .NET Framework 1.0

The assumption back then was that only one version of the CLR can be loaded into the process. This assumption lasted through .NET Fx 3.5. However, CLR 4.0 allows hosting multiple versions of CLR side-by-side in the same process and the hosting interfaces needed to reflect this.

Some hard decisions had to be made and one of those decisions is that using CLR 1.0 hosting interfaces is only good to host CLR versions up to 2.0 (i.e. .NET Framework 3.5). The only way to host .NET Framework 4.0 as well as future version of .NET is by using the new hosting interfaces.

So, how do you decide whether you want to use the new hosting interfaces or the legacy hosting interfaces? My thinking is that if you compiled against CLR 2.0 – you probably want to run in the CLR 2.0 and not require CLR 4.0 to be installed– so you will use the legacy hosting interfaces to load the CLR 2.0.

On the other hand if you compiled against CLR 4.0 or above – you have to use the new hosting interfaces to load CLR 4.0 or above.

To control which hosting interfaces to use you only need to comment out/ uncomment one line of code in CLRLoader.cpp file that is generated by the wizard. This line is at the very top of the file and is accompanied by a hefty comment:

// When loading assemblies targeting CLR 4.0 and above make sure

// the below line is NOT commented out. It enables starting

// CLR using new hosting interfaces available in CLR 4.0 and above.

// When below line is commented out the shim will use legacy interfaces

// which only allow loading CLR 2.0 or below.

#define USE_CLR40_HOSTING

By default, when we harvest the version information from the assembly we will also detect which CLR runtime the assembly is targeting – this information is available in the assembly's metadata and the Assembly Harvesting step of the wizard displays this information in the "Image Version" field. If the assembly has been compiled against CLR 2.0 - the "Image Version" field will show v2.0.5727 – the above "magic" line of code will be commented out when the files are generated.

However, if the "Image Version" does not start with v2 – the "magic" line is uncommented and this causes new hosting interfaces to be used to load the CLR

Notice that in order to use the new hosting interfaces CLR 4.0 (or above) is required to be installed on the machine. The shim compiled to use new hosting interfaces will fail to load if CLR 4.0 (or above) is missing.

When using the new hosting interfaces it is possible to load any version of the CLR installed on the box. So, the logic we are using goes like this – we first try to load the same version of the CLR the image was compiled against. This, however, can fail e.g. because this particular versoin is not installed. In this case, the shim will enumerate all the CLRs installed on the machine and pick up the latest one. The decision is made in BindToCLR4OrAbove function in CLRLoader.cpp. I am mentioning this just in case you would like to play with it.

Some sharp minds may have noticed that it is possible to use new hosting interfaces to load CLR 2.0 – however, I wanted to call out that this may not be the best course of action since you would still be requiring CLR 4.0 to be installed on the machine.

Debugging add-ins targeting CLR 2.0 in Visual Studio 2010

I had some problems debugging add-ins if those were loading in CLR 2.0. I would press F5, Excel would start up and my add-in would run but the breakpoints were not getting hit. So I wanted to share what's going on and how to set up your environment in such a way that F5 experience is not completely broken.

There is no magic in the way I usually go about debugging the shared add-in - either shimmed or unshimmed. I set a breakpoint in the OnConnection method in Connect.cs file, open project's properties, go to the Debug section, select the "Start External Program" option and set the full path to my Office application (e.g. "C:\Program Files\Microsoft Office\Office12\EXCEL.EXE"). Next I right click on the project node in the Solution Explorer and select "Set As Startup Project". When I press F5 my breakpoint is hit.

In Visual Studio 2010 the breakpoint is not hit if my add-in is loaded in CLR 2.0. What's going on is that debugger cannot attach to both CLR 4.0 and CLR 2.0 - it actually needs to know before the fact whether it should be using CLR 2.0 debugging engine or CLR 4.0 debugging engine. When you press F5 debugger tries to guess which CLR will be started in the process. The heuristic is based on reading the EXE's .config file where required runtime version is u8sually specified and if the .config file is not found than the debugger fires up the CLR 4.0 debugging engine. As we all know Office application are not bound to any particular version of the CLR so the heuristic miserably fails.

There are actually two ways of dealing with it – one is to put an <YourApp>.exe.config file alongside the.exe itself e.g. when debugging Excel 2007 I will create Excel.exe.config and leave it in the "C:\Program Files\Microsoft Office\Office12" folder.

But my preferred way of dealing with this is different. In the Solution Explorer I will right click on my solution node and select "Add" -> "Existing Project" and open "C:\Program Files\Microsoft Office\Office12\EXCEL.EXE". Next, I will right click on this newly added project and select "Set As Startup Project". Next, I will open the properties for this project and will set the "Debugger Type" property to "Managed (v2.0, v1.1, v1.0)". Now, I will F5 and the breakpoint I've set in OnConnection method will be hit.

Happy shimming everyone!

COMShimWizardSetup.msi

Comments

  • Anonymous
    March 19, 2010
    Thanks Misha! Kind regards, Dennis

  • Anonymous
    March 23, 2010
    Hi Misha, Thanks for all this wonderful information, and for the new shim wizards. Regards, Ken Slovak

  • Anonymous
    May 07, 2010
    The comment has been removed

  • Anonymous
    May 07, 2010
    Sebastian, When you build the add-in - which profile you are targeting?

  • Anonymous
    May 07, 2010
    Hi Misha, all my projects (assemblies) including my add-in are targeting the .net framework 4 client profile. For the com shim c++ project I'm am not sure if there is a dependency. Regards Sebastian

  • Anonymous
    August 25, 2010
    To target the .Net Framework 4 client profile using VS2010 you have to hand edit the .vcxproj file.  There is no way to change from full profile to client profile using the GUI.  I had to add the following 2 lines to the <Property Group Label="Globals"> ...    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>    <TargetFrameworkProfile>Client</TargetFrameworkProfile> ...

  • Anonymous
    October 25, 2010
    Very Neat - The Debugging add-ins targeting CLR 2.0 in Visual Studio 2010 saved my Bacon. Thank you for your information

  • Anonymous
    November 15, 2010
    Hello Misha, Thank you for this great tool. I just used it to shim my Word addin and all works very smoothly untill I tried to obfuscate my addin assemblies. From this point addin stopped to load and set its LoadBehavior key to 2. Same obfuscation worked well with VSTO implementation. Do you have any idea what's a problem I have? How can I debug / solve it? Thank you ahead for your help, V&G

  • Anonymous
    January 27, 2011
    Debugging add-ins targeting CLR 2.0 in Visual Studio 2010 Thank you for this advice. For Excel it is  working fine. But for PowertPoint it doesn't work. I get the message "Debugging Information for PowerPNT.exe cannot be found or does't match. Can not find or open the  PDB File. Do have any suggestions? Thank you in advance Holger

  • Anonymous
    January 29, 2011
    The comment has been removed

  • Anonymous
    March 11, 2011
    Thanks for your work! I am trying to create shimmed add-in, but can't find article which describes what I must change to create deployment project. Is there any way to make installer with Installshield LE? Ideally - than targets both x86 and x64 platforms. Does using shim solves shared add-in problems in Office 2003 (KB908002)?

  • Anonymous
    March 16, 2011
    Thx you very much for this. I was stuck on the debuggin problem where no breakpoints are hit. I made a french post about it, with a link to your website. www.thomasdupuis.com/.../francais-debugger-un-add-in-outlook-breakpoint-not-hit-visual-2010-outlook-2010 Thank you once again!

  • Anonymous
    October 16, 2011
    The comment has been removed

  • Anonymous
    January 09, 2012
    Imy company laptop locked down security allows the creation of a COM add in .exe and.msi pari, but fails on the COM SHIM.  Can you tell me the subprocesses that the IT team needs to add to the permission list to allow the creation of the COM SHIM?

  • Anonymous
    March 01, 2012
    My addin is packaged in a .exe file, so that I can distribute it with as few files as possible, and it can register itself when the end user doubleclicks the .exe. When I use the wizards to create a shim, it generates a shim that looks for <assemblyname>.dll and not .exe even though I pointed out the .exe in the wizard and it found all the necesary meta info from there. As I have zero experience in C++ it took me a while to find, but the file CLRLoader.cpp has the error in it. I changed .dll to .exe and it worked.

  • Anonymous
    March 26, 2012
    Hi  Misha Shneerson Is it possible to create a single shim for more than one Add-ins which are in same assembly? Thank You!

  • Anonymous
    May 15, 2013
    Hi Misha - We want to thank you and Andrew for writing/supporting the Com Shim Wizard.  We have used it successfully for several years. Recently we have been experiencing an issue with Com Shim Wizard 2.3.2.0. (Visual Studio 2010, Office 2010 Addin, Windows 7 32 and 64 bit applications, both utilizing .Net 4.0 Framework/CLR).   The issue relates to the repositioning of the AppDomain.Unload into the OnDisconnection module.  Many clients are experiencing 10 second delays when AppDomain.Unload is called.   It appears as if Thread.Abort, which is called during AppDomain Unload, is or becomes, a blocked thread and doesn't return back correctly.  At this point a 10-second AD timeout kicks in. After the timeout AD is forcefully torn-down, we get a CannotUnloadAppDomainException. If the AppDomain.Unload is placed back in the FinalRelease module, the 10-second AD timeout never kicks in. The end result is that if the AppDomain.Unload is called in OnDisconnection, the Office application appears to hang (Not Responding) for 10 seconds before closing.  Not a happy client experience.  If the AppDomain.Unload is called in FinalRelease the Office application closes quickly. While we understand the reasoning for the move, we have placed the AppDomain.Unload back into FinalRelease.  Do you have any alternate suggestions for a workaround for this bug fix issue? Thank you both for all your work on the Com Shim Wizard - it has been a life saver!  Any hopes of a Visual Studio 2012 Windows 8 Office 2013 version?

  • Anonymous
    May 24, 2014
    Hi Misha, I have just developed an RTD server and am interested in the Shim for RealTimeData. Can I simply use the Add-in Shim template to create the shim for my RTD automation server? Also, will the Shim Wizards work in VS 2013? Mary

  • Anonymous
    September 18, 2014
    Hi Misha I have a same problem as Mary. Is there any Shim Wizards for VS 2013?