Создайте консольное приложение .NET Core для вывода EXE

414

Для проекта консольного приложения, ориентированного на .NET Core 1.0, я не могу понять, как получить .exe для вывода во время сборки. Проект отлично работает в отладке.

Я пытался опубликовать проект, но это тоже не работает. Это имеет смысл, поскольку EXE-файл будет зависеть от платформы, но должен быть способ. Мои поиски обнаружили только ссылки на более старые версии .NET Core, которые использовали project.json.

Всякий раз, когда я создаю или публикую, это все, что я получаю:

Построить каталог

kenchilada
источник
15
Возможная копия VS2017 Compile NetCoreApp в виде EXE
Мартин Ульрих
2
@geekzster пожалуйста, удалите - я знаю, что вы не ответили на вопрос ОП, но вы ответили на мой, и я подозреваю, что у многих других было сказано dotnet <path>.dll(я не думал и печатал dotnet run <path>.dllбез успеха по понятным причинам)! (Если подумать, было бы хорошо, если бы этот вопрос был закрыт в пользу другого вопроса, на который есть аналогичный набор ответов)
Рубен Бартелинк

Ответы:

481

В целях отладки вы можете использовать файл DLL. Вы можете запустить его, используя dotnet ConsoleApp2.dll. Если вы хотите сгенерировать EXE-файл, вы должны сгенерировать автономное приложение.

Чтобы создать автономное приложение (EXE в Windows), необходимо указать целевую среду выполнения (которая зависит от целевой операционной системы).

Только до версии .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
meziantou
источник
15
Я думаю, что это может быть сделано только с CLI. Кстати, начиная с .net core 2, вам не нужно устанавливать RuntimeIdentifierв csproj.
meziantou
26
для .NET Core 2.0 это можно сделать в Visual Studio? Или я должен набрать эти команды вручную?
Томаш Сикора
77
Более 60 МБ для консольного приложения Hello world!
Shox
13
@mikolaj Есть только одна целевая среда выполнения «портативная». Есть ли способ привести все цели в? Я в порядке с использованием командной строки, однако думаю, что это шаг назад.
gsharp
10
Это не создает автономный исполняемый файл. Это создает исполняемый файл вместе с множеством других файлов (я имею в виду в папке выпуска). Включая некоторые подпапки с собственными файлами. Есть ли способ создать настоящий автономный исполняемый файл?
Мэтью
122

ОБНОВЛЕНИЕ (31 октября 2019 года)

Для тех, кто хочет сделать это через графический интерфейс и:

  • Использует Visual Studio 2019
  • Установлен .NET Core 3.0 (включен в последнюю версию Visual Studio 2019)
  • Хочет создать один файл

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

введите описание изображения здесь

Введите описание изображения здесь

Запись

Обратите внимание на большой размер файла для такого маленького приложения

Введите описание изображения здесь

Вы можете добавить свойство «PublishTrimmed». Приложение будет включать в себя только те компоненты, которые используются приложением. Внимание : не делайте этого, если вы используете отражение

Введите описание изображения здесь

Опубликуй снова

Введите описание изображения здесь


Предыдущий пост

Для тех, кто использует Visual Studio и хочет сделать это через графический интерфейс, см. Шаги ниже:

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Введите описание изображения здесь

Франсиско Вилчес
источник
19
Жаль, что вывод - это набор файлов, а не один EXE-файл, как старый .NET Framework.
Томас Карбан
2
@Tomas Karban - Так было до тех пор, пока я не изменил режим развертывания на «автономный». После изменения exe-файл также появился в папке публикации :-)
Mariusz
@TomasKarban .NET Core не является средой выполнения общего назначения. Он специально разработан для: 1) развертывания облака / контейнера, 2) мультиплатформенности. Он также должен быть временным - это всего лишь «быстрый» взлом, пока все .NET не станет открытым исходным кодом. .NET 5.0 станет следующим .NET общего назначения.
Луан
3
Тем не менее, смешно, что IDE для .NET просто не поддерживает самые основные функции, когда вы ориентируетесь на .NET Core. И это то, на что каждый должен стремиться создавать кроссплатформенные приложения командной строки - скажем, компилятор.
Восстановить Монику
18

Следующее будет производить в выходной каталог,

  • все ссылки на пакеты
  • выходная сборка
  • загрузочный 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

Саймон
источник
за исключением ($ Temp) указывает на мой C: \ Users \ ххх \ AppData \ Local \ Temp , который , очевидно , не может быть удален / очищено - ни это adviceable сделать это
Adaptabi
1
@Adaptabi Temp определяется как свойство в начале скрипта
Саймон
2

Если файл .bat приемлем, вы можете создать файл bat с тем же именем, что и файл DLL (и поместить его в ту же папку), а затем вставить следующее содержимое:

dotnet %~n0.dll %*

Очевидно, это предполагает, что на компьютере установлено .NET Core и доступно глобально.

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

(Этот ответ получен из комментария Чета .)

Амброз Леунг
источник
0

Вот мой хакерский обходной путь - создайте консольное приложение (.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();
        }
    }
}
Амброз Леунг
источник
6
Если у вас все равно будет дополнительный файл, почему бы просто не создать файл летучей мыши, который содержитdotnet [nameOfExe].dll %*
Чет