<iframe align="top" marginwidth="0" marginheight="0" src="http://www.zealware.com/46860.html" frameborder="0" width="468" scrolling="no" height="60"></iframe>
现在做.NET Framework的开发的朋友应该是越来越多了,但是可能并非人人都对MSCOREE.DLL非常了解。而事实上,毫不夸张地说,MSCOREE.DLL是.NET Framework中最为核心的DLL之一,没有这个DLL,托管程序根本无法开始执行起来,但是由于这个DLL藏在System32目录下,根本无人问津,可以说是有点委屈了这位.NET Framework中的幕后英雄。本文主要讨论MSCOREE.DLL的几大作用,以及MSCOREE.DLL的兼容性问题。
MSCOREE是托管程序的入口点
让我们来做一个小实验:
首先写一个最最简单的Hello World程序,用csc编译(当然你用VS我也没意见):
public class Program { public static void Main(string[] args) { System.Console.WriteLine("Hello World!"); } } |
然后,在命令行中键入:
C:\Windows\System32> ren mscoree.dll mscoree_.dll |
请注意在Vista系统上需提升权限,否则重命名失败。
之后,运行刚才编译出来的EXE程序。Windows直接报错:
<!--[if gte vml 1]> <![endif]--><!--[if !vml]--><!--[endif]-->
然后,再把mscoree.dll名字改回去,再次运行A.EXE,这次正确打印出了Hello World。
<!--[if gte vml 1]><![endif]--><!--[if !vml]--><!--[endif]-->
那么为什么一旦没有MSCOREE.DLL,就算是最简单的Hello World也无法运行呢?
有在Windows用C/C++编程的朋友们应该熟悉上面那个出错对话框的意思,这个对话框通常在程序找不到所需的DLL的时候出现。我们可以通过运行Visual Studio中自带的Depends.exe来查看A.EXE的对于DLL的依赖关系:
<!--[if gte vml 1]><![endif]--><!--[if !vml]--><!--[endif]-->
可以看到A.EXE只对一个DLL有依赖关系,也就是MSCOREE.DLL。并且A.EXE只用到了MSCOREE.DLL中的一个函数,即_CorExeMain。而MSCOREE.DLL本身却输出了137个函数之多。从这个函数的名字大家可以猜出,这个函数是EXE的一个入口点。为了证实这一点,我们可以用DumpBin看看内容:
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762 Copyright (C) Microsoft Corporation.All rights reserved. Dump of file a.exe PE signature found File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (x86) 3 number of sections 46C83E12 time date stamp Sun Aug 19 20:56:50 2007 0 file pointer to symbol table 0 number of symbols E0 size of optional header 10E characteristics Executable Line numbers stripped Symbols stripped 32 bit word machine OPTIONAL HEADER VALUES 10B magic # (PE32) 8.00 linker version 400 size of code 600 size of initialized data 0 size of uninitialized data 23DE entry point (004023DE) 2000 base of code 4000 base of data 400000 image base (00400000 to 00407FFF) |
注意这个EXE的入口点的RVA是23DE。
再使用Windbg加载A.EXE,使用lmm (list module match)命令查看A.EXE加载的首地址:
0:000> lmm a start end module name 00de0000 00de8000 a (deferred) |
可以看到是0x00de0000,那么再加上23DE这个RVA值,就是程序的入口点。用u命令反汇编看一下:
0:000> u de23de a+0x23de: 00de23de ff250020de00 jmp dword ptr [a+0x2000 (00de2000)] |
可以看到这就是一个简单的JUMP指令,跳转到0x00de2000所指向的位置,那么这个位置是什么函数呢?我们可以通过dds命令查看:
0:000> dds 2000+de0000 00de20005b034e50 mscoree!_CorExeMain |
到此事实就非常清楚了,任何托管的EXE程序中的入口点都是一条JMP指令直接跳转到MSCOREE.DLL的_CorExeMain函数执行。而这个_CorExeMain的地址(也就是00de2000所保存的0x5b034e50)则是由OS Loader填入,因为这个位置正是Import Table的位置。
对于一个托管的DLL而言,情况也非常类似,入口点则是_CorDllMain:
<!--[if gte vml 1]><![endif]--><!--[if !vml]--><!--[endif]-->
可以想象的到,假如你的系统中没有安装.NET Framework,那么执行托管程序也会立刻同样的对话框。显然根据这个信息用户本身很难推断出发生了什么问题。一个可行的方案是Windows总是自带一个MSCOREE.DLL,这个MSCOREE.DLL如果发现没有.NET Framework则会给出比较清晰的报错信息。不过由于从Windows 2003之后(包括Vista)的所有Windows版本都会自带.Net Framework,那么这个问题基本上不会出现了。
MSCOREE负责选择.NET Framework版本
MSCOREE.DLL有个非常特殊的地方,也就是它位于C:\Windows\System32目录下,换句话说,不管你的系统上面安装了多少个不同的.NET Framework版本,这个DLL都最多只可能有2份(32位/64位各一份),而在C:\Windows\Microsoft.NET\Framework 或者C:\Windows\Microsoft.NET\Framework64下面,则会有多份不同的.NET Framework同时存在。那么,这个MSCOREE.DLL又是如何对应不同版本的.NET Framework呢?答案很简单:MSCOREE.DLL通过注册表信息确定系统上面安装的.NET Framework版本号码,然后根据应用程序本身的所要求的版本来选择一个合适的.NET Framework版本来执行。真正的工作则是交给实际的某个版本的 .NET的DLL执行,在通常情况下,这个DLL是Work Station版本的CLR,名为MSCORWKS.DLL,而服务器版本的CLR则对应MSCORSVR.DLL
程序可以通过MSCOREE调用CLR的提供的功能或者定制CLR
MSCOREE.DLL导出了大量的函数,那么这些函数是否公开并且可以调用呢?答案是肯定的。几乎所有这些函数在MSDN中都可以查到对应的文档,并且在.NET Framework SDK的Include目录中有一个对应的mscoree.h,提供了这些函数的Prototype。应用程序通过这些函数,可以访问CLR提供的各项功能,比如:
函数名 | 用途 |
GetCORSystemDirectory | 获得进程中加载的CLR的安装目录 |
GetCORVersion | 获得进程中加载的CLR的版本西nxi |
GetFileVersion | 获得指定文件的CLR版本信息 |
GetRequestedRuntimeInfo | 获得指定版本CLR的相关信息 |
GetRequestedRuntimeVersion | 获得应用程序运行所需要的CLR版本信息 |
ClrCreateManagedInstance | 创建一个.NET对象并返回指定的接口,使用此函数可以访问大量的.NET Framework的已有功能 |
CorBindToRuntime | 加载指定版本CLR |
CorBindToRuntimeHost | 在Host中加载指定版本CLR,Hosting时候使用 |
CreateDebuggingInterfaceFromVersion | 获得对应版本CLR的ICorDebug接口,用于编写调试器(比如Visual Studio) |
CorLaunchApplication | 以指定参数启动托管程序 |
除此之外还有很多,这里只是列了一些比较常用的功能而已。可以看到这些功能都非常有用,特别值得提出的是CorBindToRuntimeHost和CreateDebuggingInterfaceFromVersion。前者提供了对CLR各个方面的定制功能,功能非常强大,有兴趣的朋友可以参考MSDN或者Customizing the Common Language Runtime一书。而后者则提供了对托管程序的调试支持,通过ICorDebug接口。
MSCOREE提供对COM支持
非托管代码可以通过COM直接调用.NET的Assembly中的托管对象。以下面这个对象为例,该对象CLSID为{0029598F-26Fa-46F7-953B-86E2947AB19F},类型为Microsoft.SqlServer.Replication.ComErrorRecord,线程模型为Both,Assembly名称为Microsoft.SqlServer.Replication, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91,所需CLR版本为v2.0.50727 (2.0 RTM)。最值得注意的是,入口点为mscoree.dll。
<!--[if gte vml 1]><![endif]--><!--[if !vml]--><!--[endif]-->
<!--[if gte vml 1]><![endif]--><!--[if !vml]--><!--[endif]-->
对于COM来说,COM只知道CLSID=0029598F-26Fa-46F7-953B-86E2947AB19F}的COM对象位于MSCOREE.DLL中。而事实上,这个类型位于Microsoft.SqlServer.Replication.dll之中,但是COM并不知道,COM只需要知道从MSCOREE.DLL中可以获得对应的ClassFactory就可以了,然后COM会通过IClassFactory接口创建这个托管对象的实例,并返回对应的接口。假定一个非托管程序尝试通过COM创建这样一个对象,那么会发生下面这些事情:
<!--[if !supportLists]-->1. <!--[endif]-->程序调用CoCreateInstance通知COM需要创建这样一个对象,CLSID=0029598F-26Fa-46F7-953B-86E2947AB19F,需要返回IDispatch接口
<!--[if !supportLists]-->2. <!--[endif]-->COM调用CoGetClassObject函数查找对应的入口DLL
<!--[if !supportLists]-->3. <!--[endif]-->COM找到对应的注册表,发现对应的DLL为MSCOREE.DLL
<!--[if !supportLists]-->4. <!--[endif]-->COM加载MSCOREE.DLL,调用DllGetClassObject函数,传入CLSID
<!--[if !supportLists]-->5. <!--[endif]-->MSCOREE.DLL中的DllGetClassObject函数读入CLSID,找到对应的注册表,获取对象的类型名称,Assembly名称,CLR版本等信息
<!--[if !supportLists]-->6. <!--[endif]-->DllGetClassObject加载对应版本的CLR
<!--[if !supportLists]-->7. <!--[endif]-->DllGetClassObject返回一个临时Class Factory对象的IClassFactory接口
<!--[if !supportLists]-->8. <!--[endif]-->COM调用这个Class Factory对象的IClassFactory::CreateInstance方法
<!--[if !supportLists]-->9. <!--[endif]-->这个Class Factory加载对应的CLR,并创建对象,返回一个对象的CCW (Com Callable Wrapper),并该CCW的返回指定的IDispatch接口
可以看到,这个情况下起到最关键作用的是MSCOREE.DLL所提供的DllGetClassObject函数。
除了对用户自定义的托管对象提供COM支持之外,MSCOREE.DLL自己也支持少量COM对象,因此MSCOREE.dll支持DllGetClassObject, DllRegisterServer, DllUnregisterServer, DllCanUnloadNow这些COM DLL所需要支持的标准函数。
MSCOREE.DLL的兼容性问题
我们可以考虑一下,假如我们现在有了.NET Framework 1.0,然后安装了.NET Framework 2.0,那么MSCOREE.DLL会发生变化吗。答案是可能会,如果到2.0到1.0发生了改变需要修改MSCOREE.DLL(比如多加了一个函数),那么肯定要更新MSCOREE.DLL,但是这个MSCOREE.DLL必须完全支持所有.NET Framework 1.0中的MSCOREE.DLL中的函数,否则可以想象所有依赖于这些变化的MSCOREE.DLL中的函数程序都会出错。因此MSCOREE.DLL必须要做到完全向前兼容。
再考虑卸载的情况,假如这个时候.NET Framework 2.0被卸载,那么MSCOREE.DLL会被还原成.NET Framework 1.0的吗?这次答案则是不会。因为2.0的MSCOREE.DLL本身支持.NET Framework 1.0,因此无须替换。这样最为简单。
事实上是,CLR Team一般很少改动MSCOREE.DLL,避免出现兼容性问题,因此可以预见,MSCOREE.DLL将会是.NET Framework/CLR中变化最少的DLL。换句话说,这篇文章的内容,在可以预见的未来几个版本基本上不会过时。OK,对于MSCOREE.DLL的讨论到这里就告一段落,有兴趣的朋友可以自己动手写一些小程序,实际体会一下MSCOREE.DLL所提供的各项功能。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1750890
相关推荐
已安装.netFramework4.0 仍提示未安装用的mscoree.dll文件及辅助工具魔方之文件解锁.exe
已安装Framework4.0,仍提示没有安装Framework4.0问题 mscoree.dll文件 32位 64位 附有魔方之文件解锁工具
mscoree.dll(互利多论坛群发2.26 提示找不到这个文件) 这里给大家下载。有这个文件, 可以注册成功。
CoreClr.DLL的库头文件,主要用于自定制CoreCLR host主机
里面包含DLL,为使用VC开发软件的哥们提供帮助!!!
文档内有详细的代码注释,...3、如果运行时还是提示找不到你调用的dll,那么将mscoree.dll也放到C:\WINDOWS\system32目录下并注册此dll。 4、如果mscoree.dll一直注册不成功,则查看是否是电脑没有安装netFramework。
dll修复工具,用于修复Windows系统各种dll的缺失。
查询文件 :C:\WINDOWS\system32\mscoree.dll 查询文件 :C:\WINDOWS\inf\unregmp2.exe 查询文件 :C:\WINDOWS\system32\shmgrate.exe 查询文件 :C:\Program Files\Outlook Express\setup50.exe 查询文件 :C:\...
找不到mscoree.lib就下载这个吧,如果不嫌麻烦就安装VS2019然后再安装.NET framework SDK,里面也有。很小的几个小东西。 下载分数不是我控制的,不知道为什么CSDN总是会自己修改这些下载分数,改得非常高
网页打印机该项目用于在Web浏览器中进行打印。例如IE6 + / Chrome / Firefox。 这个怎么运作?... 当本地服务收到命令时,它将处理... 核心:mscoree.dll 程序集:C:\ WINDOWS \ Microsoft.NET 注册表:SOFTWARE \ Micro
为了便于在 Lite 14.x 中使用大侠们的特别补丁,初步写成这个:Activator.exe 他的主要作用: 1、整合 elseif、unis、x-force、cjack 大虾的 Keygen 相对原始部署方式,这个 Activator 实现“一键激活”! 使用...
COM Interop and Regasm.exe <br> Shimming: A Solution to the Problems with MsCoree.dll Conclusion Chapter 24. Creating Outlook Add-Ins with VSTO Moving Away from ...
COM Interop and Regasm.exe <br> Shimming: A Solution to the Problems with MsCoree.dll Conclusion Chapter 24. Creating Outlook Add-Ins with VSTO Moving Away from ...
双击文件后OS Loader加载PE文件并解析,在PE Optional Header里找到基地址和RVA,通过这两个确定了程序的入口地址,这个地址指向MsCorEE.dll的_CorExeMain(),执行它。_CorExeMain()开始执行,选择加载合适版本的...
2006-03-03 23:23 20,758 mscoree.lib 2006-03-03 23:23 2,150 MSImg32.Lib 2006-03-03 23:23 7,220 MSRating.Lib 2006-03-03 23:23 52,056 MSTask.Lib 2006-03-03 23:23 6,898 MsWSock.Lib 2006-03-03 23:23 33,848...
Linux内核结构与进程管理