使CLR调用LoadLibrary或者CoCreatelnstance还算是比较简单和直接。反过来,从传统代码加载基于CLR的代码会更加有意思。
CLR最终被作为基于Win32/COM的DLL家族成员而实现。尽管使用LoadLibrary和CoCreateInstance可以直接加载这些DLL,但是没有更好的技术能将CLR加载到新进程中。事实上,鼓励非托管程序使用CLR的显式工具加载和留宿(hosting)运行时。CIR通过名为MSCOREE.DLL的DLL程序公开了这些工具。
MSCOREE.DLL有时也称为“垫片(shim)”,因为它只是CLR所包含实际DLL之前的一个外观(facade)而已。如图10.7所示,MSCOREE.DLL处于两个DLL程序的前端,MSCORWKs.DLL和MSCORSVR.DLL。其中MSCORWKS.DLL是CLR的单处理程序构建版本;MSCORSVR.DLL是CLR的多处理程序构建版本。这两个构建版本之间的主要差别是:多处理程序构建版本使用每进程、每CPU一个堆(heap),以减少竞争,单处理程序构建版本则是每进程一个堆。MSCORwKS.DLL的工作是根据众多因素,包括(但不限于)底层硬件,选择合适的构建版本。
在图10.7显示的所有DLL程序中,只有MSCOREE.DLL能在%SYSTEM.ROOT%目录下找到。为了支持多个版术的CIR的并行安装,Microsoft将所有其他DLL文件存放到版本相关的子目录下。CLR根据一系列的配置选项确定目标版本。CLR的Everett版(测试时被称为Net Framework1.1版)是真正支持CLR本身并行安装的第一个版本。
CLR有几个地方也用到著名的注册键,用于全局配置信息。机器范围的设置存于HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework下。每用户的设置则存于HKEY_CURRENT_USER\Software\Microsoft\NETFrarmework下。此外,通过设置os级环境变量,还可以覆盖许多存在注册表中的设置,例如,使用version值,可以指定运行时的默认版本。这意味着对所有用户来说,下面的.REG文件可以将默认版本号设为"v1.0.3215"。
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
VerSion=V1.0.3215
相反,在特定的命令行外壳程序(shell)中,下面的CMD.EXE命令将默认版本号设为“v1.0.3500”,用于其后所有的运行程序。
set COMPlus_Version=v1.0.3500
注意,当注册值用于环境变量时,必须加上前缀COMPlus_。对于绝人多数CLR使用的注册设置都可以使用这个约定。
在确定实现CLR的DLL名字和位置时,MSCOREE.DLL搜索Version设置和InstallRoot设置。后者指向不同版本的CLR安装的基本目录。例如.在笔者的机器中,默认没置如下所示:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
Version=v1.0.3705
InstallRoot=C:\windows\Microsfot.NET\Framework\
在查找CLR DLL文件时,MSCOREE.DLL只是简单地连接这两个值,并在C:\Windows\Microsfot.Net\Fromewrok\v1.0.3705目录下查找。你可以通过调用Sysem.Runtime.InteropServices. RuntimeEnvironment.GetRuntimeDirectory静态方法,用程序构造这个路径.同样,你也可以调用System.Runtime.InteropServices.RuntimeEnvironment.
GetRuntimeVersion静态方法提取加载的运行时Version属性。
为了确定CLR DLL实际的文件名字,MSCOREE.DLL查找更多的配置属件。如果BuildFlavor属性出现在注册表中,或者出现在进程环境变量中,MSCOREE.DLL就将那个字符串作为文件名的后缀,并以MSCOR相连接,由此产生了MSCORWKS或者MSCORSVR。注意,MSCOREE.DLL不能在单处理程序机器上加载MSCORSVR.DLL。
MSCOREE.DLL也支持被认为是兼容的新版CLR的隐式式(silent)加载。注册键.NETFramework包含一个于键Policy,它将标明绐定版本的CLR所兼容的构建号(build number)范围。当加载CLR时,MSCOREE.DLL将考察这个子键,并且,如果可能,则隐式地提升为所需的版本号。
前面提到的Version设置是与安装版本相关的,我们有可能使用配置文件,控制加载运行时的版本。如果应用程序的配置文件包含<startup >元素,那么,该版本号将覆盖注册表或环境变最中的版本。考察下面的配置文件:
<?xml version=”1.0” encoding=”utf-8” ? >
<configuration >
<startup >
<requiredRuntime version=”v1.0.2605” safemode=”false” / >
</startup >
</configuration >
这个文件表明应该使用v1.0.2605版的CLR。这里,特性safemode=“false”意味着通过版本策略,选择更高的(或者更低的)版本号是可以接受的。为了消除这个版本策略映射,你可以将safemode设为true。在这种模式下,CLR的确切版本必须是有效的,否则MSCOREE.DLL将无法加载运行时。
需要强调的是:尽管CLR支持多个版本并行安装,但是,就单个OS进程而言,只能使用一个版本。事实上,在CLR被加载到进程中时,那个进程就不可能使用其他版本,甚至在CLR的最初实例被完全卸载之后,为了支持多个CLR版本的并行执行,你必须使用多个OS进程:每个CLR版本一个进程。
有关进程范围的另一个设置就是会不会用到同步垃圾同收器。默认情况下,垃圾回收器总是运行在用于触发垃圾收集的线程上。相反,与上述的情形不同,问步垃圾回收器允许垃圾回收也在其他线程上出现。同步垃圾回收器主要适用于交互式的应用程序,这是因为存这种应用程序的主线程上运行的垃圾回收器的延迟是不可接受的。你可以使用下面的配置文件项指定同步回收器的用法:
<?xml version=”1.0” encoding=”utf-8” ? >
<configuration >
<runtime >
<gcConcurrent enabled=”true” / >
</runtime >
</configuration >
如果缺少这个元素(或者enabled特性设为false),CLR将使用常规的垃圾回收器。>