我试图通过对C#可执行文件进行ILDASM和ILASM的往返操作来重新生成一个exe文件。据我所知,由ILDASM生成的.il文件足以生成.exe文件。
我很好奇为什么.NET框架设计时要使用exe文件进行部署,而不是将.il文件部署给用户。难道C#编译器不能生成.il文件并让JIT编译器直接使用该.il文件作为输入吗?这是因为操作系统需要.exe扩展名来调用加载器,还是因为文件大小或性能考虑?
注:这个问题并没有实际意义。我问这个问题是为了让我的概念更加清晰,因为我相信我缺乏很多知识。
为了迎合.NET,增加另一种扩展名是没有任何意义的。
.NET可执行文件是PE文件,它们提供了最少量的本地代码来引导正确版本的CLR并将IL加载到内存中并移交给CLR。
Windows本地知道如何处理PE文件,并且在EXE中构建的间接机制也不需要了解.NET。
使用.il
文件,您需要向Windows注册扩展名,然后确保加载正确的CLR版本-据我所知,您只能将扩展名与一个可执行文件关联。
要支持多个CLR版本,您需要某种中介来检查您的.il
文件以确定要加载哪个CLR...之后事情变得复杂和脆弱。
将所有这些打包到PE中可以优雅地解决这些问题。
尽管这是一篇较旧的文章,但当前.NET Framework的原则仍然相同:
关键部分“ .NET标题”解释了如何工作:
Microsoft .NET环境下生成的可执行文件首先是PE文件。然而,在大多数情况下,.NET文件中的普通代码和数据都很少。.NET可执行文件的主要目的是将.NET特定信息(如元数据和中间语言(IL))加载到内存中。此外,.NET可执行文件链接到MSCOREE.DLL。这个DLL是.NET进程的起点。当.NET可执行文件加载时,它的入口点通常是一个小的代码存根。该存根只是跳转到MSCOREE.DLL中的导出函数(_CorExeMain或_CorDllMain)。从那里开始,MSCOREE接管,并开始使用可执行文件中的元数据和IL。这种设置类似于Visual Basic(.NET之前)中应用程序使用MSVBVM60.DLL的方式。.NET信息的起点是IMAGE_COR20_HEADER结构,该结构当前在.NET Framework SDK和更高版本的WINNT.H中定义的CorHDR.H中定义。IMAGE_COR20_HEADER由DataDirectory中的IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR条目指向。图10显示了IMAGE_COR20_HEADER的字段。元数据、方法IL和其他指向IMAGE_COR20_HEADER的内容的格式将在后续文章中描述。.exe
文件更小,而且它们遵循现有的标准PE格式,使Windows集成更简单。
Java需要注册.jar
扩展名并将其与单个JRE路径中的java.exe
关联。
相比之下,由于.Net程序集也是普通的Windows可执行文件,因此.Net不需要注册任何文件关联。相反,.Net EXE包含定位正确版本的运行时并调用它来执行EXE的代码。
这样,多个版本的运行时可以在同一台机器上共存,而无需一个单独的加载器打开一个.il
文件,找出它是哪个版本,然后使用正确的版本运行它。
另外,解析速度较慢;.il
文件会执行得更慢,因为运行时需要解析IL。
.exe
比.il
更为人所知了。"嘿,这个东西是个程序!" - BoltClock
.jar
文件在运行之前必须转换为字节码(据我所知),这会影响其启动时间。我是Java的新手,所以Java大师们,请纠正任何错误陈述。 - harpo