在面试中,有人问我Windows操作系统如何区分常规exe和.NET exe。
我的回答是,在构建.NET exe时,编译器会将一些信息放入头文件中,该信息是PE32或PE32+。Windows通过验证头文件来确定是否需要加载MSCOREE.dll,然后加载CLR并执行EXE。
我的答案正确吗?
在面试中,有人问我Windows操作系统如何区分常规exe和.NET exe。
我的回答是,在构建.NET exe时,编译器会将一些信息放入头文件中,该信息是PE32或PE32+。Windows通过验证头文件来确定是否需要加载MSCOREE.dll,然后加载CLR并执行EXE。
我的答案正确吗?
我认为以下两个链接是了解PE文件结构和Windows加载器的好资源。
我认为回答了你的问题的确切语句来自于2002年3月的文章:
.NET可执行文件的主要目的是将特定于.NET的信息(如元数据和中间语言(IL))加载到内存中。此外,.NET可执行文件链接到MSCOREE.DLL。该DLL是.NET进程的起点。当.NET可执行文件加载时,它的入口点通常是一个很小的代码存根。该存根只是跳转到MSCOREE.DLL中的导出函数(_CorExeMain或_CorDllMain)。 从那里开始,MSCOREE接管并开始使用来自可执行文件的元数据和IL。这种设置类似于Visual Basic(.NET之前)中应用程序使用MSVBVM60.DLL的方式。
虽然我总体上同意GregC的看法,但在某些情况下,这种类型的信息是有用的。但这是一个在面试中预期能够回答的非常困难的问题(除非是CLR团队 :))
网页和博客...
书籍...
C:\Windows\System32>dumpbin -exports mscoree.dll
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file mscoree.dll
File Type: DLL
Section contains the following exports for mscoree.dll
00000000 characteristics
4AF3AF84 time date stamp Fri Nov 06 07:09:24 2009
0.00 version
17 ordinal base
126 number of functions
123 number of names
ordinal hint RVA name
38 0 0001AAA0 CLRCreateInstance
... Lots of stuff left out...
136 76 00015030 _CorDllMain
138 77 00004DDB _CorExeMain
137 78 0001A981 _CorExeMain2
139 79 0002033B _CorImageUnloading
140 7A 000042D0 _CorValidateImage
24 00008017 [NONAME]
142 00014C4D [NONAME]
Summary
4000 .data
4000 .reloc
1000 .rsrc
40000 .text
这是一个棘手的问题。你得到了这份工作吗?;-)
我知道已经过了一段时间,但对于任何寻找答案的人:
答案可以在MSDN中找到:https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/corvalidateimage-function
在Windows XP和更高版本中,操作系统加载程序通过检查通用对象文件格式(COFF)头中的COM描述符目录位来检查托管模块。设置的位表示托管模块。如果加载程序检测到托管模块,则加载MsCorEE.dll并调用_CorValidateImage...
您可以使用 dumpbin /clrheader
自行检查(原生模块将为空)。
如果您考虑一下(至少在.NET4+中),这必须在进程启动之前由加载程序完成(这意味着您不能等待模块调用CLR初始化例程),因为AnyCPU表示加载程序动态确定进程的位数,在进程启动之前必须明确知道。