Reputation: 2919
I was asked in an interview as to how Windows OS differentiate between a regular EXE and a .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.
Is my answer correct?
Upvotes: 31
Views: 8748
Reputation: 593
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://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/corvalidateimage-function
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...
You can check this yourself with dumpbin /clrheader
(which will be empty for a native module).
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.
Upvotes: 2
Reputation: 22443
While I agree with GregC in 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 :)
Web Pages and Blogs...
Books...
Upvotes: 6
Reputation: 171
I think that the following two links are a good resource to get an understanding the PE file structure and the Windows loader.
The exact quote from the March 2002 article, which I believe answers your question, is:
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.
Upvotes: 17
Reputation: 53699
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.
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
Upvotes: 5