对于一个以. net Core 1.0为目标的控制台应用程序项目,我不知道如何在构建过程中输出一个.exe。该项目在调试中运行良好。

我试过发布这个项目,但也不行。这是有意义的,因为EXE文件是特定于平台的,但必须有一种方法。我的搜索只找到了使用project.json的旧。net Core版本。

每当我构建或发布时,我得到的都是:


当前回答

下面是我的简单解决方法——生成一个控制台应用程序(。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();
        }
    }
}

其他回答

出于调试目的,可以使用DLL文件。您可以使用dotnet ConsoleApp2.dll运行它。如果要生成EXE文件,则必须生成一个自包含的应用程序。

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

Pre -。仅限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

更新:FEB2022 下面的内容仍然适用于。net 6

更新。net 5!

以下内容适用于。net 5正式发布后的2020年11月。

(请参阅下面的快速术语部分,而不仅仅是如何操作)

指南(CLI)

Pre-requisites

下载最新版本的。net 5 SDK。链接

步骤

打开一个终端(例如: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)

Pre-requisites

如果阅读2020年11月之前:最新版本的Visual Studio预览* 如果阅读NOV2020+:最新版本的Visual Studio*

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

步骤

右键单击Project,然后单击Publish 单击“开始”,选择“文件夹目标”,单击“下一步”,选择“文件夹” 输入任意文件夹位置,然后单击Finish 点击编辑 选择一个目标运行时,勾选生成单个文件并保存。* 点击发布 在您发布应用程序的位置打开一个终端,并运行.exe。例子:

这里有一些术语

目标运行时 请参阅RID的列表

部署模式

框架依赖是指生成一个小的。exe文件,但app假设主机上安装了。net 5 自包含意味着一个更大的。exe文件,因为。exe包含了框架,但是你可以在任何机器上运行。exe,不需要预安装。net 5。注意:当使用自包含时,将产生额外的依赖项(.dll),而不仅仅是.EXE

启用ReadyToRun编译 TLDR:它相当于。net 5的提前编译(AOT)。预编译为本地代码,应用程序通常会启动得更快。应用程序更性能(或没有!),取决于许多因素。更多信息请点击这里

修整未使用的组件 当设置为true时,dotnet将生成一个非常精简和小的.exe,只包含它需要的内容。这里要小心。示例:当在应用程序中使用反射时,你可能不想将此标志设置为true。

微软文档


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

dotnet %~n0.dll %*

显然,这假设机器已经安装了。net Core,并且在全球可用。

c:\> "path\to\batch\file" -args blah

(这个答案来自Chet的评论。)

下面将在输出目录中生成:

所有包引用 输出程序集 bootstrapping 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

下面是我的简单解决方法——生成一个控制台应用程序(。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();
        }
    }
}