Crie um aplicativo de console do .NET Core para gerar um EXE

413

Para um projeto de aplicativo de console direcionado ao .NET Core 1.0, não consigo descobrir como obter um arquivo .exe durante a compilação. O projeto corre bem na depuração.

Eu tentei publicar o projeto, mas isso também não funciona. Faz sentido, pois um arquivo EXE seria específico da plataforma, mas deve haver uma maneira. Minhas pesquisas apenas encontraram referências às versões mais antigas do .NET Core que usavam project.json.

Sempre que eu construo ou publico, é tudo o que recebo:

Diretório de compilação

kenchilada
fonte
15
Possível duplicata do VS2017 Compile NetCoreApp como EXE
Martin Ullrich
2
@geekzster, por favor, cancele a exclusão - eu sei que você não respondeu à pergunta do OP, mas você respondeu à minha, e suspeito que muitos outros disseram dotnet <path>.dll(eu não estava pensando e digitando dotnet run <path>.dllsem sucesso por razões óbvias)! (Na reflexão que seria bom se isso foi fechado em favor da outra questão que tem um conjunto semelhante de respostas)
Ruben Bartelink

Respostas:

480

Para fins de depuração, você pode usar o arquivo DLL. Você pode executá-lo usando dotnet ConsoleApp2.dll. Se você deseja gerar um arquivo EXE, é necessário gerar um aplicativo independente.

Para gerar um aplicativo independente (EXE no Windows), você deve especificar o tempo de execução de destino (específico do sistema operacional que você segmenta).

Apenas antes do .NET Core 2.0 : primeiro, adicione o identificador de tempo de execução dos tempos de execução de destino no arquivo .csproj ( lista de RIDs suportados ):

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

A etapa acima não é mais necessária a partir do .NET Core 2.0 .

Em seguida, defina o tempo de execução desejado ao publicar seu aplicativo:

dotnet publish -c Release -r win10-x64
dotnet publish -c Release -r ubuntu.16.10-x64
meziantou
fonte
15
Eu acho que isso pode ser feito apenas com a CLI. BTW, começando com .net core 2, você não precisa configurá-lo RuntimeIdentifierno csproj.
precisa saber é o seguinte
26
para .NET Core 2.0, isso pode ser feito no Visual Studio? Ou devo digitar esses comandos manualmente?
Tomasz Sikora 21/10
77
Mais de 60 MB para um aplicativo de console Hello World!
shox
13
@mikolaj Há apenas um tempo de execução de destino "portátil". Existe uma maneira de trazer todos os alvos? Eu estou bem em usar a linha de comando, no entanto, acho que é um passo atrás.
precisa saber é
10
Isso não cria um executável independente. Isso cria um executável, juntamente com uma série de outros arquivos (na pasta de lançamento, quero dizer). Incluindo algumas subpastas com seus próprios arquivos. Existe uma maneira de criar um verdadeiro executável independente ?
18719 Matthew Matthew
122

ATUALIZAÇÃO (31-OUT-2019)

Para quem quiser fazer isso por meio de uma GUI e:

  • Está usando o Visual Studio 2019
  • O .NET Core 3.0 está instalado (incluído na versão mais recente do Visual Studio 2019)
  • Quer gerar um único arquivo

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

insira a descrição da imagem aqui

Digite a descrição da imagem aqui

Nota

Observe o tamanho do arquivo grande para um aplicativo tão pequeno

Digite a descrição da imagem aqui

Você pode adicionar a propriedade "PublishTrimmed". O aplicativo incluirá apenas componentes usados ​​pelo aplicativo. Cuidado : não faça isso se estiver usando reflexão

Digite a descrição da imagem aqui

Publicar novamente

Digite a descrição da imagem aqui


Postagem anterior

Para quem está usando o Visual Studio e deseja fazer isso via GUI, consulte as etapas abaixo:

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Francisco Vilches
fonte
19
Pena que a saída é um monte de arquivos, não apenas um EXE como o antigo .NET Framework.
Tomas Karban
2
@Tomas Karban - Foi o caso até que eu mudei o modo de implantação para "auto-suficiente" Depois de arquivo de mudança exe apareceu na publicação pasta também :-)
Mariusz
O @TomasKarban .NET Core não é um tempo de execução de uso geral. Ele foi projetado especificamente para 1) implantação em nuvem / contêiner, 2) multiplataforma. Ele também deve ser temporário - é apenas um hack "rápido" até que todo o .NET possa ser aberto. O .NET 5.0 será o próximo .NET de uso geral.
Luaan 12/08/19
3
Ainda assim, é ridículo que o IDE para .NET simplesmente não ofereça suporte à funcionalidade mais básica quando você está direcionando o .NET Core. E é isso que todos devem ter como alvo para criar aplicativos de linha de comando de plataforma cruzada - digamos, um compilador.
Reponha Monica
18

O seguinte produzirá, no diretório de saída,

  • todas as referências de pacote
  • o conjunto de saída
  • o bootstrapping exe

Mas ele não contém todos os assemblies de tempo de execução do .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>

Eu o envolvi em uma amostra aqui: https://github.com/SimonCropp/NetCoreConsole

Simon
fonte
exceto o ($ Temp) pontos para o meu c: \ Users \ xxx \ AppData \ Local \ Temp que obviamente não pode ser removido / limpo - nem é adviceable a fazê-lo
Adaptabi
1
@Adaptabi Temp é definido como uma propriedade no início do script
Simon
2

Se um arquivo .bat for aceitável, você poderá criar um arquivo bat com o mesmo nome que o arquivo DLL (e colocá-lo na mesma pasta) e colar no seguinte conteúdo:

dotnet %~n0.dll %*

Obviamente, isso pressupõe que a máquina tenha o .NET Core instalado e disponível globalmente.

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

(Esta resposta é derivada do comentário de Chet .)

Ambrose Leung
fonte
0

Aqui está minha solução hacky - gere um aplicativo de console (.NET Framework) que leia seu próprio nome e argumentos e depois chame dotnet [nameOfExe].dll [args].

Obviamente, isso pressupõe que o .NET esteja instalado na máquina de destino.

Aqui está o código. Sinta-se livre para copiar!

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();
        }
    }
}
Ambrose Leung
fonte
6
Se você deseja ter um arquivo adicional de qualquer maneira, por que não apenas criar um arquivo bat que contenhadotnet [nameOfExe].dll %*
Chet