COM Interop and regasm.exe





COM Interop and regasm.exe

The mechanism for loading COM add-ins into Office was developed long before .NET existed and relies entirely on a technology called COM to instantiate the COM add-in. For a COM add-in written in Visual Basic to be used in Office, it must be registered as a COM component. The ability to register a Visual Basic class as a COM component is a core feature of the CLR called COM interop and can be achieved easily by running the regasm.exe tool on the assembly containing your Connect class or by selecting the Register setting for the primary output assembly in the setup project.

The regasm.exe tool works by reading the declaration of your class and in particular the classlevel attributes GuidAttribute and ProgID, shown in Listing 23.5. These classlevel attributes are defined in the System.Runtime.InteropServices namespace. The GuidAttribute tells the regasm.exe tool what CLSID to use in the registry for the class when registering it under HKEY_CLASSES_ROOT\CLSID. The ProgID tells the regasm.exe tool what ProgID to use when registering the class. The regasm.exe tool writes the necessary keys only under HKEY_CLASSES_ROOT\CLSID. The required key for the add-in with the ProgID name under HKEY_CURRENT_USER\Software\Microsoft\Office\%appname%\Addins and associated key values are not added by regasm.exe and must be added by custom install actions in the installer.

The Attributes in the Connect Class That Are Looked at by regasm.exe

Imports System.Runtime.InteropServices

<GuidAttribute("910322B9-AF60-4C4F-9FEE-9ABEE4A16FAE"), _
ProgIdAttribute("MyAddin1.Connect")> _
Public Class Connect

End Class

mscoree.dll and Managed AddIns

A managed component registered under HKEY_CLASSES_ROOT\CLSID differs from a typical unmanaged COM component primarily with regard to the InProcServer32 key in the registry for the component. An unmanaged component would set the InProcServer32 to be the DLL that implements the COM component. A managed component cannot set this value to the name of the managed DLL, because to create an instance of the managed assembly, the CLR needs to be loaded, and there is no guarantee that the calling application will already have loaded the CLR into memory. In fact, it is almost certain that the calling application will not have loaded the CLR, because it is trying to load what it thinks is a COM component. To circumvent this chickenandegg situation, the CLR provides a DLL called mscoree.dll that loads the CLR, instantiates the class out of the managed assembly, and returns a COM Callable Wrapper for the managed class to the calling application.

When a managed class is registered by regasm.exe, the InProcServer32 key for the assembly always has a default value of mscoree.dll, and an additional set of registry values is set that mscoree.dll uses to load the managed class. These additional keys provide information about the managed class and assembly that mscoree.dll will create and load. Figure.13 shows these values under a typical HKEY_CLASSES_ROOT\CLSID\{some guid}\InProcServer32 key for a managed add-in class called Connect in an assembly called WordAddin1.

13. The values under the InProcServer32 key for a typical managed COM add-in.


All managed COM add-ins created by the Shared AddIn Wizard use mscoree.dll to get loaded into the Office process. Unfortunately, this presents several problems for Office COM add-in development that have led to the need for replacing the mscoree.dll with a different custom loadersometimes called a shimwhen building COM add-ins for Office applications.

Note

If you are targeting Outlook 2003, you do not need to use a shim; you can use the new VSTO Outlook add-in project type that solves the problems associated with mscoree.dll.


Problems with Using mscoree.dll to Load Your COM AddIn

Problem 1: mscoree.dll Can Be Disabled, Causing All Managed COM AddIns to Stop Loading

Office is composed of some of the most widely used applications in the world, and ensuring that the Office applications remain as stable as possible is a key concern for the Office development team. Because Office is so widely used, a number of COM add-ins have been designed to run inside Office applications. Unfortunately, not all of them are written well, and they crash. When a COM add-in crashes, the hosting Office application becomes unstable or often crashes itself, leaving the user with little or no way of knowing what on earth happened.

Microsoft invested heavily in the crashdetection and reporting system in Office XP to try to track down these crashes in Office. While doing this, it quickly realized that many crashes were a result of thirdparty COM add-ins that were crashing. Using this information, Microsoft introduced the ability to detect when a COM add-in crashes during Officeapplication startup. On the next run of the application, Office displays a dialog box, such as the one shown in Figure.14, offering to disable the COM add-in.

14. Office offers to disable a COM add-in.


If the user clicks the Yes button, Office will "blacklist" the COM add-in so that it will not be loaded into Office until an update has been received from the vendor. Although this is a great step forward for the reliability of Office applications, the way it was implemented does not work well with the default registration mechanism for managed COM add-ins, because Office believes that the offending DLL is mscoree.dll, which it blocks. Blocking mscoree.dll will block not only the crashing COM add-in, but also every other managed COM add-in registered for that Office application.

Problem 2: mscoree.dll Cannot Be Signed

In the late 1990s, Office was plagued with viruses such as the Melissa virus that took advantage of the ability to run code contained in an Office document. To defend against such attacks, Microsoft introduced several security measures in Office XP primarily aimed at stopping malicious VBA code from running, but also to mitigate potential risks from COM add-ins. The primary defense against an add-in was to introduce the capability to load only COM add-ins signed by a trusted publisher. On the surface, this seems like a great idea, and indeed it is for unmanaged COM components. Unfortunately, it does not work well with the default registration mechanism for managed COM add-ins, because Office checks the signature of the InProcServer32 binary, which is always mscoree.dll, not the managed DLL started by mscoree.dll, which contains the managed COM add-in. mscoree.dll is a system DLL that is not signed and is installed by the CLR, so signing it with your own certificate is not possible. mscoree.dll cannot be signed because it cannot vouch that the components it loads are safe.

Luckily, the default setting for Office is to trust all installed add-ins, even if they are not signed, so this problem is not one that you will encounter in all Office installations. But it does mean that if a company or individual is particularly security conscious and unchecks the Trust All Installed AddIns and Templates setting in the Security dialog box, shown in Figure.15, your COM add-in will not run. This dialog box can be invoked by choosing the Security item from the Macros submenu of the Tools menu in most Office applications.

15. The Trust All Installed AddIns and Templates option in the Security dialog box.


Problem 3: mscoree.dll Loads All COM AddIns into the Same AppDomain

Whenever managed code is loaded into an unmanaged application, the CLR must be hosted inside the application to run the managed code. Hosting the CLR is something that can be achieved implicitly or explicitly. Implicit hosting of the CLR is achieved by the unmanaged application's talking to mscoree.dll (which advertises itself as a COM object), which in turn starts the CLR in the application and loads the managed code. Alternatively, the application can host the CLR directly by using the CLR hosting APIs, which provide considerable control over how the CLR gets loaded and in particular how assemblies get loaded. None of the Office 2003 applications hosts the CLR directly with respect to COM add-ins (although Word and Excel do host the CLR for documentbased customizations created by Visual Studio Tools for Office), so all COM add-ins are loaded via their InProcServer32 setting.

When the CLR is running inside a host application, it can load managed code into a unit of isolation called an AppDomain. You can think of an AppDomain as a little miniprocess running inside the Office application process. Each VSTO codebehinddocument solution loads into its own AppDomain. So when you have three Excel workbooks loaded in the Excel process with VSTO code behind them, an AppDomain is created for each workbook. These AppDomains are isolated from one another; code in one AppDomain cannot adversely affect the other AppDomains. Also, when the workbook is closed, the AppDomain corresponding to it can be stopped and unloaded without affecting the running code in other AppDomains.

By default, mscoree.dll loads managed COM add-ins into the same AppDomainan AppDomain known as the default AppDomain. This is bad, because the COM add-ins are all running in the same AppDomain and can easily adversely affect one another. Also, there is no mechanism to unload managed code that was loaded when a COM add-in was connected but is no longer needed when the COM add-in is disconnected, because the default AppDomain cannot be unloaded until the Office process exits. What you really want is for each COM add-in to load into its own AppDomain instead of loading all together into the default AppDomain.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows