Windows 如何区分常规 EXE 和 .NET exe?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2638883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does Windows differentiate between a regular EXE and a .NET exe?
提问by AlwaysAProgrammer
I was asked in an interview as to how Windows OS differentiate between a regular EXE and a .NET EXE.
我在一次采访中被问到 Windows 操作系统如何区分常规 EXE 和 .NET EXE。
My reply was, when a .NET exe is build, the compiler puts some information into the header. The information is PE32 or PE32+. Windows verifies the header to determine if it needs to load MSCOREE.dll which loads the CLR and executes the EXE.
我的回答是,当构建 .NET exe 时,编译器会将一些信息放入标头中。信息为 PE32 或 PE32+。Windows 验证标头以确定它是否需要加载 MSCOREE.dll,后者加载 CLR 并执行 EXE。
Is my answer correct?
我的回答正确吗?
采纳答案by Matthew Whited
While I agree with GregCin general there are times when this type of information is useful. But that is one tough question to be expected to answer in an interview (unless it's for the CLR team :)
虽然我总体上同意GregC 的观点,但有时此类信息很有用。但这是一个很难在面试中回答的问题(除非是针对 CLR 团队的:)
Web Pages and Blogs...
网页和博客...
Books...
图书...
- Expert .NET 2.0 IL Assembler(I thought this was a great book)
- Expert .NET 2.0 IL Assembler(我认为这是一本很棒的书)
回答by Doruk
I think that the following two links are a good resource to get an understanding the PE file structure and the Windows loader.
我认为以下两个链接是了解 PE 文件结构和 Windows 加载程序的好资源。
- An In-Depth Look into the Win32 Portable Executable File Format(MSDN Mag Feb 2002)
- An In-Depth Look into the Win32 Portable Executable File Format, Part 2(MSDN Mag Mar 2002)
- 深入了解 Win32 可移植可执行文件格式(MSDN Mag 2002 年 2 月)
- 深入了解 Win32 可移植可执行文件格式,第 2 部分(MSDN Mag 2002 年 3 月)
The exact quote from the March 2002 article, which I believe answers your question, is:
我相信 2002 年 3 月文章中的确切引述可以回答您的问题:
The primary purpose of a .NET executable is to get the .NET-specific information such as metadata and intermediate language (IL) into memory. In addition, a .NET executable links against MSCOREE.DLL. This DLL is the starting point for a .NET process. When a .NET executable loads, its entry point is usually a tiny stub of code. That stub just jumps to an exported function in MSCOREE.DLL (_CorExeMain or _CorDllMain). From there, MSCOREE takes charge, and starts using the metadata and IL from the executable file. This setup is similar to the way apps in Visual Basic (prior to .NET) used MSVBVM60.DLL.
.NET 可执行文件的主要目的是将特定于 .NET 的信息(例如元数据和中间语言 (IL))获取到内存中。此外,.NET 可执行文件链接到 MSCOREE.DLL。此 DLL 是 .NET 进程的起点。 当 .NET 可执行文件加载时,其入口点通常是一小段代码。该存根只是跳转到 MSCOREE.DLL (_CorExeMain 或 _CorDllMain) 中的导出函数。从那里,MSCOREE 负责,并开始使用来自可执行文件的元数据和 IL。此设置类似于 Visual Basic(.NET 之前)中的应用程序使用 MSVBVM60.DLL 的方式。
回答by Chris Taylor
In brief, and it has been a while so some of this might be a little dated...
简而言之,已经有一段时间了,所以其中一些可能有点过时了......
For XP and later, the OS loader is enhanced to detect managed assemblies based on a PE directory entry, if the directory entry is present the loader automatically loads the mscoree.dll and a jump is made to a function in mscoree, _CorExeMain(2) for executables and _CorDllMain for dlls. _CorExeMain is then responsible for loading the CLR and kickstarting the execution of the managed code.
对于 XP 及更高版本,OS 加载程序得到增强,可以根据 PE 目录条目检测托管程序集,如果目录条目存在,加载程序会自动加载 mscoree.dll 并跳转到 mscoree 中的函数 _CorExeMain(2)对于可执行文件和 _CorDllMain 对于 dll。然后 _CorExeMain 负责加载 CLR 并启动托管代码的执行。
I used the following to remind myself of the entry point names...
我使用以下内容来提醒自己入口点名称...
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
回答by Eli Finkel
Tough question. Did you get the job? ;-)
棘手的问题。你得到这份工作了吗?;-)
I know it's been a while, but for anyone looking for an answer: The answer can be found in MSDN here: https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/corvalidateimage-function
我知道已经有一段时间了,但对于任何寻找答案的人:答案可以在 MSDN 中找到:https: //docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/corvalidateimage-功能
In Windows XP and later versions, the operating system loader checks for managed modules by examining the COM Descriptor Directory bit in the common object file format (COFF) header. A set bit indicates a managed module. If the loader detects a managed module, it loads MsCorEE.dll and calls _CorValidateImage...
在 Windows XP 和更高版本中,操作系统加载程序通过检查通用对象文件格式 (COFF) 标头中的 COM 描述符目录位来检查托管模块。设置位指示受管模块。如果加载器检测到托管模块,它会加载 MsCorEE.dll 并调用 _CorValidateImage...
You can check this yourself with dumpbin /clrheader
(which will be empty for a native module).
您可以自己检查dumpbin /clrheader
(对于本机模块,它将为空)。
If you think about it (at least in .NET4+), this must be done by the loader before the process starts (meaning you could not wait for the module to call CLR initialization routines) because AnyCPU means the loader dynamically determines the bitness of the process, which obviously must be known before the process starts.
如果您考虑一下(至少在 .NET4+ 中),这必须在进程开始之前由加载程序完成(意味着您不能等待模块调用 CLR 初始化例程),因为 AnyCPU 意味着加载程序动态确定过程,这显然必须在过程开始之前就知道。