In my last article, I briefly discussed how COM, Sxs and CLR work together to make registration free COM/.Net interop possible. Today, I want to dive a bit deeper into this feature. Specifically, I want to discuss
1. How activation works end to end.
2. How to generate manifests for managed assemblies
3. What are the constraints of registration free COM interop.
In a typical Registration Free COM interop scenario, there is a managed assembly as the COM server. The managed assembly has a SxS manifest describing the COM registration information. There is also an unmanaged COM client. The client has a Sxs manifest with the managed COM server as its dependency.
During the COM activation, the following sequences happen in order:
1. CreateProcess is called on the COM client
2. Inside CreateProcess, Sxs detects that the COM client has a Sxs manifest.
3. Sxs parses the client’s manifest. For all the dependencies specified in the client’s manifest, Sxs finds the manifests and parses them as well. This process continues until all the dependencies closure are found and parsed. The parsed result is stored in the process default activation context. These all happen inside Sxs so the sxs behavior discussed in Sxs --- Activation Context, Binding, Policy and Probing is applicable.
4. After CreateProcess, the COM client calls CoCreateInstance (as an example), with a CLSID described in the managed COM server’s sxs manifest.
5. COM asks Sxs if Sxs know anything about this CLSID.
6. Sxs looks up the current activation context, finds this CLSID, realizes this is defined for a managed COM server, and returns mscoree.dll as the inproc server.
7. COM loads mscoree.dll, and calls mscoree!DllGetClassObject with the CLSID.
8. Mscoree.dll loads mscorwks.dll (the CLR execution engine), and transfers the CLSID to mscorwks.dll.
9. Mscorwks.dll asks Sxs for information about this CLSID
10. Sxs finds the CLSID in the current activation context, retrieves its assembly identity, type name, among other information, and returns them to mscorwks.dll
11. Mscorwks.dll calls Assembly.Load() on the assembly identity. Once the assembly is loaded successfully, mscorwks.dll activates the type, and returns.
During this process, COM, Sxs and CLR cooperate very tightly to achieve the registration free COM interop scenario.
Sxs manifests for managed assemblies
Sxs manifests closely mirrors what RegAsm.exe puts into registry. In the current implementation, there are three categories:
1. CLR Classes
When RegAsm registers a CLR class, it writes the type name, assembly identity, threadingmodel, progid and runtimeversion. In the sxs manifests for managed assemblies, the following syntax can be used to describe CLR classes
For managed types, the threadingModel has to be “Both”. The runtimeVersion is the version of CLR used to build the assembly. For .Net framework, it will be “v1.0.3705” for 1.0, “v1.1.4322” for 1.1, and “v2.0.50727” for 2.0.
2. COM Imported types
TlbImp.exe can be used to generate a COM Interop assemblies for unmanaged COM Servers. For COM imported types, they will share the same CLSID as the unmanaged COM Servers. clrClass cannot be used for COM imported types. If the unmanaged COM Server has a sxs manifest, there will have two COM Servers with the same GUID but different names. This is illegal under COM rules. For this reason, during activation context creation, if sxs encounters two manifests declaring the same CLSID, sxs will fail the activation context creation. To avoid this problem, a new tag clrSurrogate is invented. When this element is encountered, Sxs will not fail the activation context creation if it finds another manifest declaring the same CLSID.
RegAsm only registers the assembly identity, the type name and the runtimeVersion for COM imported types. The following syntax can be used for COM imported types in sxs manifests:
Clsid, name and runtimeVersion are the only attributes allowed in clrSurrogate element. Using any other element will cause a Sxs manifest parse error.
3. CLR Value types
Start from .Net framework 1.1, CLR supports exporting value types from managed assemblies for COM interop.
RegAsm registers CLR value types under HKCR\Record. It only registers assembly identity and type name. Since this is essentially the same information about COM imported types, the clrSurrogate element is re-used for value types.
4. Interop assemblies
For a fully registration free COM environment, everything has to be included in the transitive closure of sxs manifests. Since Interop assemblies depend on the underline unmanaged COM server, the unmanaged COM server needs to have a sxs manifest, and the sxs manifest of the interop assembly needs to declare the unmanaged COM server as a dependency.
There are two important components in activation path: Sxs and CLR. Each of them has their own deployment model. They are similar but with subtle difference. The deployment must satisfy the constraints of both components.
1. Assembly Identity
There are two assembly identities in the registration free COM Interop scenario: The managed assembly identity in the .Net assembly, and the native assembly identity in the sxs manifest. On activation, CLR retrieves the native assembly identity from SxS, then uses the same identity to find the managed assembly. This means, the two assembly identities must be identical.
2. Binding Policies
Both SxS and CLR have their own binding policies. Each of them understands their own binding policies, but not the other one’s binding policies. This has some interesting consequence.
For example, in .Net framework, an application references a v1 component. You can install v2 of the component, and use a binding policy to redirect v1 to v2. Now even v1 of the component does not exist on the machine, the application will run fine.
Not in registration free COM interop. SxS does not understand CLR policies. When the application declares that it depends on v1 of the component, SxS will search for sxs binding policies for the component (which does not exist), then try to find v1 of the component. Since v1 of the component does not exist, this will fail.
Thus, in registration free COM interop scenario, when you change a component, you need to either leave the old component in a place Sxs can find, or change the application manifest to point to the new component’s identity, or add/change the sxs binding policy to redirect to the new component.
There are essentially two probing happened per activation for each component. First Sxs will probe for the sxs dependencies, later CLR will probe for the managed assembly.
This means, the assembly must be discoverable for both Sxs and CLR.
Both Sxs and CLR have the concept of GAC (Sxs call it WinSxs) and Application Base. If Sxs and CLR have different Application Base, and the component is not in GAC, then one of them will fail to find the component. In that case, the only way to enable registration free COM interop is to install the component to GAC. Sxs understands GAC and will find the component in GAC.
Sxs’ isolation boundary is Activation Context, while CLR’s isolation boundary is AppDomain. There is no one-to-one relationship between Activation Context and AppDomain. When CLR queries information from Sxs, Sxs uses the current activation context. It is the developer’s responsibility to transit to the right activation context before calling into COM.
Other frequently asked question about registration free COM interop
1. Registration free COM interop in classic ASP
You can enable Sxs assemblies in IIS6 on Windows Server 2003.
Unfortunately this does not work for registration free COM interop. This is due to constraint 3) discussed above: The application base for Sxs is the web application’s directory, but the CLR application base for the default appdomain is the process directory (where w3wp.exe resides, typically %windir%\system32\inetsrv.). The workaround is to install the managed assembly to GAC.
2. Registration free COM interop in ASP.Net
This by default does not work either, due to constrain 4). But work can be done to enable this scenario.
Other Resources on Registration Free COM Interop
I come across the Side-By-Side Manifest Maker site when I search registration free COM interop in internet. This site has some very interesting discussion on the very topic, especially on the howto page. You may want to check it out.
Other references listed below.
Isolated Applications and Side-by-side Assemblies
Registration-Free COM Interop
Registration-Free Activation of .NET-Based Components: A Walkthrough
Simplify App Deployment with ClickOnce and Registration-Free COM
COM activation, Registration Free COM activation, COM/.Net Interop, Registration Free COM/.Net Interop
Sxs --- Activation Context, Binding, Policy and Probing
Genman32 – A tool to generate Sxs manifest for managed assembly for Registration Free COM/.Net Interop