【问题标题】:Why do .NET Core and .NET 5 generate an executable?为什么 .NET Core 和 .NET 5 会生成可执行文件?
【发布时间】:2020-06-05 22:11:19
【问题描述】:

我有一个非常困惑的问题。我对.NET的理解是这样的:

  • C# 应用程序(源代码)->
  • csc.exe(编译器)->
  • .NET 应用程序(在 MSIL 中)

如果是这样,为什么构建 .NET 应用程序的输出是 Windows 可执行文件?我认为整个想法是您的源代码编译为 MSIL,它以本地安装的 CLR 为目标。但是,.NET Core 和 .NET 5 都会生成一个 windows 可执行文件,它运行在操作系统之上,而不是在虚拟机中。

这与 Java 不同,Java 编译为 .class 字节码文件(不是 .exe),这些文件确实在虚拟机上运行(或者,稍后,您可以将所有将类文件放入.jar)。

我想问的是:为什么 C# 编译器不生成在 .NET 上运行的特定应用程序文件类型?例如,与公共语言运行时关联的 .net 文件?

我最好的猜测是,生成的 Windows .exe 实际上不是,而是一个 Windows 可执行文件,而是某种 .NET 可执行文件。但是,在那种情况下,为什么它不能在任何带有 .NET Core 的平台上运行呢? Linux 不知道.exe 文件是什么。

【问题讨论】:

  • 好问题!尽管需要 JIT 编译器,但许多新开发人员只是认为这是理所当然的,并接受它“正常工作”这一事实,而没有真正调查为什么它可以工作。
  • 另外,欢迎来到 .NET 开发!您正在一个激动人心的时刻学习,因为此时开发模型确实非常成熟,具有跨平台和框架的统一开发体验。
  • .NETCore 实际上就是这样工作的。 .jar 的等价物是 .dll,java.exe 的等价物是 dotnet.exe。但是在 18 年的程序员已经习惯了运行 .exe 之后,.NETCore 和 VS 并没有试图过多地破坏苹果车。您运行的 .exe 是“主机”,它的工作是实现 VM。程序员迟早会习惯只分发 .dll,这可能需要一段时间。

标签: .net .net-core cil .net-5


【解决方案1】:

它是一个常规的可执行文件,但它包含的唯一本机代码是一个小存根,它将调用 .NET 运行时。然后,运行时将检查嵌入在该文件中的 MSIL 并完成剩下的工作。

【讨论】:

    【解决方案2】:

    正如其他答案已经回答的那样,Windows 上的默认设置是生成一个小型主机可执行文件,用于启动 .NET 运行时并加载适当的 MSIL 程序集。

    一个有趣的事实是,MSIL 程序集以与所有 windows .exe 或 .dll 文件相同的运行时格式(“PE”- 可移植可执行文件)打包..

    早期版本的“新 .NET”(.NET Core,现在是 .NET 5+)只生成了可以在所有平台上运行的 .dll 文件,并且要求用户使用dotnet theapp.dll 来运行应用程序。

    虽然这可行,但 .NET Core 3.0 及更高版本也开始生成“应用程序主机”程序集作为替代入口点。 dotnet publish 生成的代码仍然是跨平台的,但是另外生成可执行文件有几个优点:

    • 将经典 .NET Framework 项目迁移到 .NET Core 需要在具有 CI/CD 管道或需要 .exe 文件的工具的大型项目中进行较少更改。
    • 用户可以更轻松地在任务资源管理器/ps 中找到正确的程序 - 就像找到正确的 java.exe 进程一样,周围有数百个 dotnet.exe 进程对于操作任务来说有点困难。
    • dotnet.exedotnet (linux / macOS) 的路径可能很难找到或设置。通过使用可执行文件,它可以在各个地方查找运行时,并且较少依赖于正确设置的 PATH 环境变量。
    • 在 Windows 上,人们可能希望更改 .exe 的特定于操作系统的定义,例如:
      • 子系统标志(GUI 与控制台应用程序):.exe 文件中的标志控制窗口是否打开控制台窗口。 java 有 java.exejavaw.exe 用于控制台和 GUI 程序。 .NET Core 3.0+ 应用所需的设置可以通过构建过程或项目 SDK(例如 WinForms、WPF)进行自定义。
      • 嵌入式图标:Windows .exe 文件可以包含图标。如果您希望您的应用(尤其是 GUI 应用)显示在资源管理器或任务栏中并带有图标,您需要一个 .exe 文件,您可以使用图标进行实际修改。
      • 嵌入 Win32 清单:清单文件可以控制很多事情,例如提升的访问要求(这些 .exe 文件会提示您允许管理员访问)。又是你不能用 dotnet.exe theapp.dll 做的事情。

    请注意,由于 Apple 的公证要求,目前在 macOS 上禁用此可执行文件生成。 (基本上,您需要对应用程序进行签名,而苹果需要对其进行“公证”才能在没有警告的情况下运行)。

    【讨论】:

    • "生成了一个小型主机可执行文件" 可执行文件有 140,000 字节,大得离谱。比较 .NET Framework 生成的可执行文件:不到 5,000 字节,并且已经包含“hello world”程序,它在 .NET 5 中仍然是一个单独的 DLL。
    【解决方案3】:

    因为微软希望生成的代码可以直接执行。即他们不想要

    c:> rundotnet myapp
    

    他们想要

    c:> myapp
    

    为什么,因为用户现在必须知道如何运行某些东西,而不是仅仅键入或单击它。因此,他们将 IL 封装在一个引导 exe 中,该 exe 加载了 .net 运行时并进入了 IL 的主入口点。

    将此与正在运行的 Java 应用程序进行比较。

    注意单声道(在 linux 上)你做了

    #: mono myapp
    

    虽然后来他们介绍了一种以 w​​indows 方式进行的方式

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-28
      • 1970-01-01
      相关资源
      最近更新 更多