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

Lau*_*835 6 .net cil .net-core .net-5

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

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

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

This is unlike Java, which compiles to a .class bytecode file (not an .exe), and those files do run atop a virtual machine (or, later, you can package all the class files into a .jar).

What I'm trying to ask is: Why doesn't the C# compiler generate a specific application file type that runs atop .NET? E.g., a .net file that is associated with the common language runtime?

My best guess is that the Windows .exe generated is not, in fact, a Windows executable, but instead some kind of .NET executable. But, in that case, why can't it run on any platform with .NET Core? Linux doesn't know what an .exe file is.

Mar*_*ich 7

正如已经回答的其他答案一样,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进程对于 ops 任务来说有点困难。
  • dotnet.exedotnet(linux / macOS)的路径可能很难找到或设置。通过使用可执行文件,它可以在不同位置查找运行时,并且对正确设置的 PATH 环境变量的依赖性较小。
  • 在 Windows 上,人们可能想要更改 .exe 的特定于操作系统的定义,例如:
    • 子系统标志(GUI 与控制台应用程序):.exe 文件中的标志控制 Windows 是否打开控制台窗口。java 有java.exejavaw.exe用于控制台与 GUI 程序。.NET Core 3.0+ 应用程序所需的设置可以通过构建过程或项目 SDK(例如 WinForms、WPF)进行自定义。
    • 嵌入式图标:Windows .exe 文件可以包含图标。如果您希望您的应用程序(特别是 GUI 应用程序)在资源管理器或任务栏中显示一个图标,您需要一个 .exe 文件,您可以实际使用该图标进行修改。
    • 嵌入 Win32 清单:清单文件可以控制很多事情,例如提升访问要求(这些 .exe 文件将提示您允许管理员访问)。又是你不能用dotnet.exe theapp.dll.

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


The*_*kis 6

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