Invoking the Default Host: Activating Managed Types Through COM Interop
The Microsoft .NET Framework software development kit (SDK) includes a tool (regasm.exe) you can use to make managed types available through COM. In this way, a managed type can be brought into a process using any of the existing COM APIs. regasm.exe works by creating the registry entries necessary to make the type visible to COM. The default host for managed types activated in this way is also implemented in the CLR startup shim (mscoree.dll). In this scenario, the default host is activated because regasm.exe sets the CLR startup shim as the InProcServer32 key under the COM registry entries for all managed types. Figure 4-1 shows the registry entries that regasm.exe would make to allow the managed type System.Collections.SortedList to be activated through COM.
Figure 4-1. Registry entries that expose a managed type to COM
When an instance of
is created through COM, the shim loads the CLR in the process and returns a class factory through which COM can create the type. The CLR determines which type it needs to create by looking back in the registry for the globally unique identifier (GUID)/ProgID
Defaults for the CLR Startup Options
Selecting a CLR Version
The process for selecting the version of the CLR to load into the process is more involved and is different depending on whether the default host is activated to run a managed executable or to load a managed type through COM. The version to load is not hard-coded into the host as the other settings are, but rather varies based on which version of the CLR was used to build the assembly about to be run and which versions of the CLR are present on the machine.
Running Managed Executables
Embedded in every assembly is the version of the CLR used when the assembly was built. For example, if you build an assembly with the .NET Framework SDK 1.1 (included in Microsoft Visual Studio .NET 2003), your assembly will contain the version number 1.1.4322the version of the CLR included in .NET Framework 1.1. Keep in mind that the version number I am discussing here is not
The samples for this book include a utility called clrversion.exe that can be used to display the version of the CLR used to build a particular assembly. Just invoke clrversion.exe from the command line with the
C:\>clrversion SimpleExe.exe SimpleExe.exe was built with v1.1.4322 of the CLR
The tool clrversion.exe is useful for helping you determine why the shim is choosing a particular version of the CLR when many are installed on the machine.
When running a managed code executable, the default host begins by looking in the assembly to determine which version of the CLR was used to build the file. It then looks in the registry to determine whether that version of the CLR is installed on the machine. It also determines whether any upgrades to that version should be applied (more on this later in the chapter). If the version of the CLR used to build the executable is installed, the startup shim loads that version of the CLR to run the program. For more details on what these registry keys look like and how the shim maps a version number to a given CLR, see Chapter 3.
If the version of the CLR used to build the executable is not installed on the machine, the shim might choose to run the program with a later version of the CLR. It's important to remember that an upgrade is not applied in all circumstances. The shim chooses to run an application with a later version of the CLR only if the following two conditions are true:
If these two conditions are met, the shim looks to see whether a
For example, the Upgrades registry key shown in Figure 4-2 indicates that version 1.1.4322 of the CLR is compatible with version 1.0.3705. Because 1.1.4322 is intended to be compatible with 1.0.3705, the shim will use version 1.1.4322 of the CLR to run an application built with 1.0.3705 (but remember, this happens only if 1.0.3705 isn't present on the machine and the application doesn't have a configuration file that states a version preference).
Figure 4-2. The Upgrades registry key
Let's look at a few examples to see how the shim behaves when the conditions for an upgrade are met. Say you have a program myapp.exe that was built with CLR version 1.0.3705. Regardless of whether a newer, compatible version of the CLR is present, myapp.exe will always be run with 1.0.3705 if that version is installed on the machine. Figure 4-3 shows the application running with the version it was built with, even though a newer, compatible version is present.
Figure 4-3. Applications run with the CLR version they are built with by default.
However, if CLR version 1.0.3705 is not installed, but version 1.1.4322 is, the application is run with 1.1.4322 because the Upgrades key identifies it as a suitable upgrade. This scenario is shown in Figure 4-4.
Figure 4-4. Applications can be run with a newer, compatible version of the CLR.
Remember that this behavior occurs only when the default host has not been customized using a configuration file. I explore the details of how to specify a CLR version using an application configuration file later in the chapter.
Activating Managed Types Through COM Interop
The shim's algorithm for picking a version in the COM interoperability scenario is much more straightforwardthe latest version installed on the machine is always used. This "use latest" behavior might sound like taking the easy way out, but in fact the alternatives are no more desirable. In the interoperability scenario discussed previously, the executable that started the process clearly contains no information about CLR versions because it is not a managed code file. So no information is available when the process starts to hint at which version to use.
The managed assemblies that get loaded through COM interoperability do contain the version of the CLR they were built with just like managed executables do. It's tempting to think that the version of the CLR to load can be determined by looking at the assembly the shim has been asked to load through COM. This approach might work fine if the application were to load only one assembly, but it can fall apart if multiple assemblies are to be loaded. In this case, each assembly might have been built with a different version of the CLR. Therefore, the first one to be loaded determines the version of the CLR that would run all assemblies in the process (recall that only one version of the CLR can exist in a process). In many scenarios, the order in which multiple assemblies are loaded is not
For example, consider an application that supports an add-in model based on COM. The addins for this application can be written in managed code as long as the appropriate COM interfaces are provided to hook into the application. If the
Scenarios like these are the primary reason the shim always selects the latest CLR in situations in which managed code is first brought into the process through COM. Although choosing the latest version relies on a high degree of compatibility between releases of the CLR, it at least keeps the behavior of this type of application consistent.
This behavior of using the latest CLR will likely