为什么 .NET Core 和 .NET 5 生成可执行文件?

Why do .NET Core and .NET 5 generate an executable?

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

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

这与 Java 不同,后者编译成 .class 字节码文件(不是 .exe),而那些文件 do 运行 在虚拟机上(或者,稍后,您可以将所有 class 文件打包成 .jar)。

我想问的是:为什么 C# 编译器不生成 运行 基于 .NET 的特定应用程序文件类型?例如,与通用语言 运行time?

关联的 .net 文件

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

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

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

c:> rundotnet myapp

他们想要

c:> myapp

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

将此与 运行宁 java 个应用程序进行比较。

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

#: mono myapp

虽然后来他们引入了一种方法 windows

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

一个有趣的事实是,MSIL 程序集以与所有 windows .exe 或 .dll 文件相同的 运行time 格式(“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 上,人们可能想要更改 OS 特定于 .exe 的定义,例如:
    • 子系统标志(GUI 与控制台应用程序):.exe 文件中的标志控制 windows 是否打开控制台 window。 java 有 java.exejavaw.exe 用于控制台程序与 GUI 程序。 .NET Core 3.0+ 应用程序所需的设置可以通过构建过程或项目 SDK(例如 WinForms、WPF)进行自定义。
    • 嵌入式图标:Windows.exe 文件可以包含图标。如果您希望您的应用程序(尤其是 GUI 应用程序)在资源管理器或任务栏中显示一个图标,您需要一个 .exe 文件,您可以使用该图标实际修改。
    • 嵌入 Win32 清单:清单文件可以控制很多事情,例如更高的访问要求(这些 .exe 文件会提示您允许管理员访问)。同样是 dotnet.exe theapp.dll.
    • 做不到的事情

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