构建.NET Core控制台应用程序以输出一个EXE文件

480
针对一个针对.NET Core 1.0的控制台应用程序项目,我无法弄清楚如何在构建期间获取.exe输出。该项目在调试中运行良好。
我已经尝试了发布该项目,但也无法解决。这是有道理的,因为.exe文件是特定于平台的,但肯定有办法。我的搜索只找到了旧版.NET Core使用project.json的参考文献。
每当我构建或发布时,都只会得到这个: Build directory

15
可能是VS2017编译NetCoreApp为EXE的重复问题。 - Martin Ullrich
2
@geekzster 请恢复删除 - 我知道你没有回答 OP 的问题,但是你通过说 dotnet <path>.dll 回答了我的问题,我还怀疑其他许多人也是这样。 (我没有考虑清楚,一直在尝试 dotnet run <path>.dll,显然是行不通的)!(经过反思,最好关闭此问题,支持另一个具有类似答案集的问题)。 - Ruben Bartelink
有人可以帮我吗?https://dev59.com/VmsMtIcB2Jgan1znzbII - aldo
5个回答

540

为了调试,您可以使用DLL文件。您可以使用dotnet ConsoleApp2.dll运行它。如果您想生成EXE文件,则必须生成自包含应用程序。

要生成自包含应用程序(在Windows中为EXE),必须指定目标运行时(特定于您针对的操作系统)。

仅适用于.NET Core 2.0之前的版本:首先,在.csproj文件中添加目标运行时的运行时标识符(支持的RID列表):

<PropertyGroup>
    <RuntimeIdentifiers>win10-x64;ubuntu.16.10-x64</RuntimeIdentifiers>
</PropertyGroup>

从.NET Core 2.0开始,不再需要上述步骤。

然后,在发布应用程序时设置所需的运行时:

dotnet publish -c Release -r win10-x64
dotnet publish -c Release -r ubuntu.16.10-x64

15
我认为这只能通过CLI完成。顺便说一下,从.net core 2开始,在csproj中不需要设置“RuntimeIdentifier”。 - meziantou
31
.NET Core 2.0可以在Visual Studio中完成吗?还是我必须手动输入这些命令? - Tomasz Sikora
89
一个打印“Hello world”文本的控制台应用程序占用了超过60MB的空间! - shox
13
@mikolaj只有一个目标运行时"portable"。有没有办法将所有目标整合在一起?我可以使用命令行,但认为这是一种退步。 - gsharp
13
这不会创建一个独立的可执行文件。这将创建一个可执行文件,以及一系列其他文件(我指的是发布文件夹中的文件),其中包括一些带有自己文件的子文件夹。是否有一种方法可以创建真正的__独立__可执行文件? - Matthew
显示剩余17条评论

207

更新:2022年2月

.NET 6仍然适用以下内容。

.NET 5的更新!

以下内容适用于/在2020年11月.NET 5正式发布之后。

(请参见下面的快速术语部分,不仅仅是操作说明)

如何操作(CLI)

前提条件

  • 下载最新版本的 .NET 5 SDK。 链接

步骤

  1. 打开终端(例如:bash、命令提示符、powershell),并在与 .csproj 文件相同的目录中输入以下命令:
dotnet publish --output "{any directory}" --runtime {runtime}
  --configuration {Debug|Release} -p:PublishSingleFile={true|false}
  -p:PublishTrimmed={true|false} --self-contained {true|false}

例子:

dotnet publish --output "c:/temp/myapp" --runtime win-x64 --configuration Release
  -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true

如何使用GUI界面发布.NET5单文件应用程序

前置要求

  • 如果阅读日期在2020年11月之前:最新版的Visual Studio Preview*
  • 如果阅读日期在2020年11月之后:最新版的Visual Studio*

* 上述两种情况下,最新的.NET5 SDK将自动安装在您的PC上。

步骤

  1. 右键单击项目,然后点击“发布”
    进入图像描述

  2. 点击“开始”,选择“文件夹目标”,然后点击下一步,选择文件夹 选择文件夹目标

  3. 输入任何文件夹位置,然后点击“完成”

  4. 点击“编辑”
    进入图像描述

  5. 选择目标运行时,勾选“生成单个文件”,然后保存。* 进入图像描述

  6. 点击“发布”

  7. 在您发布应用程序的位置打开终端,然后运行.exe文件。例如: 进入图像描述

一些术语

目标运行时
查看RID列表

部署模式

  • 框架依赖表示生成了一个小型.exe文件,但应用程序假定主机机器上已安装.NET 5
  • 自包含表示生成了一个较大的.exe文件,因为.exe包括框架,但是您可以在任何机器上运行.exe,不需要预先安装.NET 5。注意:使用自包含时,将生成其他依赖项(.dll),而不仅仅是.exe文件

启用ReadyToRun编译
TLDR:这是.Net5的Ahead of Time Compilation(AOT)等价物。预编译为本地代码,应用程序通常会更快地启动。应用程序的性能更高(或者不是!),取决于许多因素。更多信息在此处

修剪未使用的程序集
当设置为true时,dotnet将生成非常精简和小巧的.exe文件,并且仅包括必要的内容。请小心。例如:当在应用程序中使用反射时,您可能不希望将此标志设置为true。

Microsoft文档



23
很遗憾,输出是一堆文件,而不是像旧版的.NET Framework那样只有一个EXE文件。 - Tomas Karban
3
在我将部署模式更改为"self-contained"之前,情况是这样的。在更改后,exe文件也出现在发布文件夹中 :-) - Mariusz
@TomasKarban .NET Core 不是通用的运行时。它专门设计用于 1) 云/容器部署,2) 多平台。它也意味着是临时的 - 它只是一个“快速” hack,直到所有的 .NET 可以被开源。.NET 5.0 将成为下一个通用的 .NET。 - Luaan
1
这对我没有用。我尝试了许多组合,但我的可执行文件仍然无法显示我的程序内容,一个非常简单的“Hello World”。一年内发生了什么变化吗? - Katherine
直到我移除了 --configuration 标志,它才对我起作用。 - Shad

20
以下内容将在输出目录中生成:
  • 所有软件包引用
  • 输出程序集
  • 引导exe
但它不包含所有的.NET Core运行时组件。
<PropertyGroup>
  <Temp>$(SolutionDir)\packaging\</Temp>
</PropertyGroup>

<ItemGroup>
  <BootStrapFiles Include="$(Temp)hostpolicy.dll;$(Temp)$(ProjectName).exe;$(Temp)hostfxr.dll;"/>
</ItemGroup>

<Target Name="GenerateNetcoreExe"
        AfterTargets="Build"
        Condition="'$(IsNestedBuild)' != 'true'">
  <RemoveDir Directories="$(Temp)" />
  <Exec
    ConsoleToMSBuild="true"
    Command="dotnet build $(ProjectPath) -r win-x64 /p:CopyLocalLockFileAssemblies=false;IsNestedBuild=true --output $(Temp)" >
    <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
  </Exec>
  <Copy
    SourceFiles="@(BootStrapFiles)"
    DestinationFolder="$(OutputPath)"
  />

</Target>

我在这里提供了一个示例:https://github.com/SimonCropp/NetCoreConsole


1
除非($Temp)指向我的c:\Users\xxx\AppData\Local\Temp,否则显然无法删除/清理它 - 也不建议这样做。 - DATEx2
1
@Adaptabi Temp 在脚本开头被定义为一个属性。 - Simon

4

如果可以使用 .bat 文件,您可以创建与 DLL 文件同名的 bat 文件(并将其放置在同一文件夹中),然后粘贴以下内容:

dotnet %~n0.dll %*

显然,这需要机器安装并全局可用.NET Core。
c:\> "path\to\batch\file" -args blah

(本答案源自Chet的评论。)

0

这是我的hacky解决方法 - 生成一个控制台应用程序(.NET Framework),它读取自己的名称和参数,然后调用dotnet [nameOfExe].dll [args]

当然,这假设目标机器上已安装.NET。

以下是代码。随意复制!

using System;
using System.Diagnostics;
using System.Text;

namespace dotNetLauncher
{
    class Program
    {
        /*
            If you make .NET Core applications, they have to be launched like .NET blah.dll args here
            This is a convenience EXE file that launches .NET Core applications via name.exe
            Just rename the output exe to the name of the .NET Core DLL file you wish to launch
        */
        static void Main(string[] args)
        {
            var exePath = AppDomain.CurrentDomain.BaseDirectory;
            var exeName = AppDomain.CurrentDomain.FriendlyName;
            var assemblyName = exeName.Substring(0, exeName.Length - 4);
            StringBuilder passInArgs = new StringBuilder();
            foreach(var arg in args)
            {
                bool needsSurroundingQuotes = false;
                if (arg.Contains(" ") || arg.Contains("\""))
                {
                    passInArgs.Append("\"");
                    needsSurroundingQuotes = true;
                }
                passInArgs.Append(arg.Replace("\"","\"\""));
                if (needsSurroundingQuotes)
                {
                    passInArgs.Append("\"");
                }

                passInArgs.Append(" ");
            }
            string callingArgs = $"\"{exePath}{assemblyName}.dll\" {passInArgs.ToString().Trim()}";

            var p = new Process
            {
                StartInfo = new ProcessStartInfo("dotnet", callingArgs)
                {
                    UseShellExecute = false
                }
            };

            p.Start();
            p.WaitForExit();
        }
    }
}

7
既然您肯定要创建一个额外的文件,为什么不直接创建一个批处理文件,其中包含 dotnet [nameOfExe].dll %* 命令呢?这样可以更加方便地运行程序。 - Chet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接