2011-03-30 103 views
20

我试图通过执行ILDASM和ILASM在C#可执行文件上的往返来重新生成一个exe文件。据我所知,由ILDASM生成的.il文件足以生成.exe。为什么IL代码打包到C#应用程序中的exe文件中?

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

PS:这个问题没有实际意义。我问这个问题让我的概念更清楚,因为我相信我缺乏很多。

+0

+1好问题。为了比较,这将更接近于Java部署的工作原理 - 对吗? '.jar'文件在运行之前必须转换为字节码(据我了解),这会影响其启动时间。我是Java新手,所以Java大师,请纠正任何错误陈述。 – harpo 2011-03-30 17:29:40

+0

你在问关于文件内容还是扩展名? – SLaks 2011-03-30 17:35:37

+0

Slaks - 我想知道两者。更多的信息更好.. – paseena 2011-03-30 17:38:11

回答

4

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

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

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

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

+1

更不用说'.exe'是一个比'.il'更好的已知格式。 “嘿,这是一个程序!” – BoltClock 2011-03-30 17:24:27

+1

@Bolt:这并没有阻止Java。 – SLaks 2011-03-30 17:25:30

+0

除非NGen'd它仍然是IL包裹在需要被JIT'DE EXE所以实际上没有任何速度上的差异。 – Kev 2011-03-30 17:26:09

0

.Net运行时/ JIT使用IL的字节码表示。这与编译成机器代码的程序集类似。与仅仅试图将IL保持为“可执行”代码相比,它的影响更小,更容易验证二进制数据的完整性。它也会使文件变大。

15

为了迎合.NET,添加其他类型的扩展是没有任何意义的。

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

Windows本身就知道如何处理PE文件以及内置在EXE中的间接机制Windows也不需要了解.NET。

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

要支持CLR的多个版本,您需要某种中介,然后检查您的.il文件以确定要加载哪个CLR ....并且事情在此之后变得复杂而脆弱。

在PE中打包所有这些问题整洁而优雅地解决了这些问题。

虽然这是一篇较旧的文章,但其原理在当前保持不变。NET框架:

An In-Depth Look into the Win32 Portable Executable File Format, Part 2

的关键部分 “的.NET头” 解释了这是如何工作:针对Microsoft .NET 环境下生产

可执行文件是第一和最重要的 PE文件。但是,在大多数情况下,在.NET 文件中的正常代码和数据是最小的。 .NET可执行的主要目的是 得到.NET特定 信息,例如元数据 和中间语言 (IL)到存储器中。另外,一个针对MSCOREE.DLL的.NET 可执行链接。 这个DLL是一个 .NET进程的起点。当加载一个.NET可执行文件 时,其入口点通常是一个 微小的代码段。这存根只是 跳转到 MSCOREE.DLL(_CorExeMain或 _CorDllMain)导出函数。从那里,MSCOREE负责并开始使用 元数据和来自可执行文件 的IL。此设置与使用MSVBVM60.DLL的Visual Basic(.NET之前) 中的应用程序的 类似。 .NET信息的起始点 是 IMAGE_COR20_HEADER结构, 当前在CorHDR.H中从 .NET Framework SDK和更新的 版本的WINNT.H中定义。在DataDirectory中, IMAGE_COR20_HEADER被 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 条目指向。图10 显示了一个 IMAGE_COR20_HEADER的字段。所述 元数据的格式,方法IL,和其他东西 通过 将在随后的 文章描述IMAGE_COR20_HEADER指向。窗户

+2

值得注意的是,从XP开始,CLR引导代码就不再使用了。它必须在那里,因为这就是.NET exes如何被指定的,但OS加载器知道如何加载.NET可执行文件。 – 2011-03-31 12:43:22

+2

@damien - 你有这个信息的链接? – Kev 2011-03-31 13:01:56

2

早期版本有.net的任何操作系统级别的支持。这导致一些替代方案:

  1. 一个exe文件加载.net CLR,然后使用它来运行IL。这样做的缺点是你无法区分包含.net IL的exe文件和本机exe文件。如果你想用减少的.net权限运行它,这是相关的。
    该程序与本地程序一目了然可能会导致更高的接受度。
    它还允许用.net程序替换原生程序,而无需更改所有调用它的代码。
  2. 包含二进制IL的新文件格式。类似于java的jar文件。双击时,它们将与关联的程序一起打开。像“rundotnet.exe myprogram.net”。
    这会导致假定程序可执行文件与逻辑程序之间存在一对一映射的程序出现问题。这包括防火墙和任务栏分组功能。在任务管理器看不到什么多个“rundotnet.exe”是你所看见的,...
    和组件混合了本地和.NET代码是不可能用这种解决办法。
    这样做的一大好处是程序代码可以在执行前由.net运行时验证。
  3. 具有新文件扩展名的PE文件。这是我最喜欢的一个。在旧版本的Windows中,您可以简单地添加一个注册表项来运行是一个正常的程序,在新版本中,您可以给它特殊的处理。这避免了2和3的问题。

有了内置的操作系统支持,就可以避免大部分单独文件格式的问题。选择1)超过2)是可以理解的,但我不知道他们为什么不选择3.我的猜测是他们喜欢让所有(现代)可执行文件具有相同的文件扩展名。

相关问题