为什么IL代码打包到C#应用程序的exe中?

pas*_*ena 21 .net c# clr

我试图通过对ILDASM进行往返,然后在C#可执行文件上进行ILASM来重新生成exe.据我所知,ILDASM生成的.il文件足以生成.exe文件.

我很好奇为什么.NET框架被设计为使用exe文件进行部署而不是将.il文件部署到用户.c#编译器无法生成.il文件,JIT编译器直接使用.il文件作为输入吗?是因为操作系统需要.exe扩展来调用加载器,还是因为文件大小或性能方面的考虑?

PS:这个问题没有实际意义.我问这个问题让我的概念更加清晰,因为我确信我缺乏很多.

Kev*_*Kev 17

为了迎合.NET而添加另一种类型的扩展是没有任何意义的.

.NET可执行文件是PE文件,它们提供最少量的本机代码来引导正确版本的CLR并将IL拉入内存并交给CLR.

Windows本身知道如何处理PE文件,并且内置于EXE中的间接机制Windows也不需要了解.NET.

使用.il文件,您需要在Windows中注册扩展名,然后确保加载了正确版本的CLR - 据我所知,您只能将扩展名与一个可执行文件相关联.

为了支持CLR的多个版本,您需要某种中介,然后检查您的.il文件以确定要加载哪个CLR ......然后事情就会变得复杂和脆弱.

将所有这些包装在PE中可以整齐而优雅地解决这些问题.

虽然这是一篇较旧的文章,但在当前的.NET框架中,原则仍然相同:

深入研究Win32可移植可执行文件格式,第2部分

关键部分"The .NET Header"解释了这是如何工作的:

为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中定义.DataDirectory中的IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR条目指向IMAGE_COR20_HEADER.图10显示了IMAGE_COR20_HEADER的字段.IMAGE_COR20_HEADER指向的元数据格式,方法IL和其他内容将在后续文章中描述.

  • 值得注意的是,从XP开始,不再使用CLR引导代码.它必须存在,因为这是.NET exes的规范,但OS加载器知道如何加载.NET可执行文件. (2认同)
  • @damien - 你有这个信息的链接吗? (2认同)

SLa*_*aks 5

.exe文件更小。
它们还遵循现有的标准 PE 格式,使 Windows 集成更简单。

Java 需要注册.jar扩展并将其关联java.exe到单个 JRE 的路径中。

相比之下,由于 .Net 程序集也是普通的 Windows 可执行文件,因此 .Net 不需要注册任何文件关联。相反,.Net EXE 包含定位正确版本的运行时并调用它来执行 EXE 的代码。
这允许多个版本的运行时在同一台机器上共存,而不需要一个单独的加载器来打开.il文件,找出它是什么版本,然后用正确的版本运行它。

此外,解析速度很慢;.il文件会执行得更慢,因为运行时需要解析 IL。

  • @Kev:读取 CIL 字节码比解析字符串更快更容易。 (3认同)
  • @slaks - 好吧,我重读了一遍,我知道你来自哪里,但我认为 OP 将 IL 汇编器语句与编译器发出的结果 MSIL 混淆。 (2认同)