为什么 .NET Core 和 .NET 5 生成可执行文件?
Why do .NET Core and .NET 5 generate an executable?
我有一个很困惑的问题。我对.NET的理解是这样的:
- C# 应用程序(源代码)->
csc.exe
(编译器)->
- .NET 应用程序(在 MSIL 中)
如果是,为什么构建 .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.exe
或 dotnet
(linux / macOS) 的路径可能很难找到或设置。通过使用可执行文件,它可以在各个地方查找 运行时间,并且较少依赖于正确设置的 PATH 环境变量。
- 在 windows 上,人们可能想要更改 OS 特定于 .exe 的定义,例如:
- 子系统标志(GUI 与控制台应用程序):.exe 文件中的标志控制 windows 是否打开控制台 window。 java 有
java.exe
和 javaw.exe
用于控制台程序与 GUI 程序。 .NET Core 3.0+ 应用程序所需的设置可以通过构建过程或项目 SDK(例如 WinForms、WPF)进行自定义。
- 嵌入式图标:Windows.exe 文件可以包含图标。如果您希望您的应用程序(尤其是 GUI 应用程序)在资源管理器或任务栏中显示一个图标,您需要一个 .exe 文件,您可以使用该图标实际修改。
- 嵌入 Win32 清单:清单文件可以控制很多事情,例如更高的访问要求(这些 .exe 文件会提示您允许管理员访问)。同样是
dotnet.exe theapp.dll
. 做不到的事情
请注意,由于 Apple 的公证要求,目前在 macOS 上禁用此可执行文件生成。 (基本上你需要签署应用程序,苹果需要对其进行“公证”才能 运行 没有警告)。
我有一个很困惑的问题。我对.NET的理解是这样的:
- C# 应用程序(源代码)->
csc.exe
(编译器)->- .NET 应用程序(在 MSIL 中)
如果是,为什么构建 .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.exe
或dotnet
(linux / macOS) 的路径可能很难找到或设置。通过使用可执行文件,它可以在各个地方查找 运行时间,并且较少依赖于正确设置的 PATH 环境变量。 - 在 windows 上,人们可能想要更改 OS 特定于 .exe 的定义,例如:
- 子系统标志(GUI 与控制台应用程序):.exe 文件中的标志控制 windows 是否打开控制台 window。 java 有
java.exe
和javaw.exe
用于控制台程序与 GUI 程序。 .NET Core 3.0+ 应用程序所需的设置可以通过构建过程或项目 SDK(例如 WinForms、WPF)进行自定义。 - 嵌入式图标:Windows.exe 文件可以包含图标。如果您希望您的应用程序(尤其是 GUI 应用程序)在资源管理器或任务栏中显示一个图标,您需要一个 .exe 文件,您可以使用该图标实际修改。
- 嵌入 Win32 清单:清单文件可以控制很多事情,例如更高的访问要求(这些 .exe 文件会提示您允许管理员访问)。同样是
dotnet.exe theapp.dll
. 做不到的事情
- 子系统标志(GUI 与控制台应用程序):.exe 文件中的标志控制 windows 是否打开控制台 window。 java 有
请注意,由于 Apple 的公证要求,目前在 macOS 上禁用此可执行文件生成。 (基本上你需要签署应用程序,苹果需要对其进行“公证”才能 运行 没有警告)。