.NET CORE - Como criar um executável e publicar um pacote independente
O objetivo desse artigo é detalhar como criar uma aplicação .NET Core Console através da ferramenta de linha de comando (.NET CLI - DOTNET Command Line Interface) e do Visual Studio Code.
O primeiro passo é baixar o SDK do .NET Core, disponível para download em: .NET SDK. Observe que é possível realizar o download para várias plataformas, por exemplo:
- Windows
- Linux (RHEL, Ubuntu, Linux Mint, Debian, Fedora, CentOS, Oracle Linux e openSUSE)
- Mac
- Docker
O .NET Core SDK fornece um conjunto de bibliotecas e ferramentas para criar aplicações e bibliotecas .NET Core. Após a instalação, por padrão, o .NET SDK está localizado em C:\Program Files\dotnet\SDK. Observe que lá existem todas as versões instaladas do .NET Core (side-by-side):
O .NET Core é baseado em um conjunto de pacotes NuGet que permite otimizar as aplicações para ser dependente apenas dos módulos necessários. Isso reduz o tempo necessário para testar e implantar atualizações que não são usadas pela aplicação.
Como as funcionalidades do .NET Framework estão agrupadas em pacotes NuGet, o tempo de atualização e entrega desses pacotes é muito menor. Não é necessário aguardar uma atualização do framework como um todo.
Os pacotes NuGet, instalados pelo .NET Core SDK, ficam disponíveis para uso no diretório .nuget\packages do perfil do usuário:
Para criar uma nova aplicação, via linha de comando, abra o prompt de comando (ou PowerShell) e crie um diretório:
mkdir C:\temp\HelloWorldConsole
cd .\Temp\HelloWorldConsole
O .NET Core SDK fornece a ferramenta de linha de comando (.NET Core CLI) através do executável dotnet. Para listar os comandos disponíveis para a ferramenta, digite:
dotnet -h
Observe que existem, por padrão, os seguintes comandos:
Para criar uma nova aplicação do tipo Console é necessário utilizar o comando new. Para listar os tipos de projetos que o comando oferece, digite o seguinte comando:
dotnet new -h
Observe que o comando new oferece a opção de escolhe a linguagem (C# ou F#), através do parâmetro -l, e o tipo de projeto, através do parâmetro -t, conforme:
Os tipos de projetos que o .NET CLI disponibiliza são:
- Console
- Web
- Lib
- xunittest
Para criar uma nova aplicação console, digite o seguinte comando:
dotnet new -t console
Os seguintes arquivos serão criados:
- Program.cs
- project.json
O arquivo Program.cs contém o código-fonte da aplicação:
namespace ConsoleApplication
{
public class Program
{
public static void Main (string [] args)
{
Console.WriteLine ( "Hello World!");
}
}
}
Observe que o código é a mesma a de uma aplicação C# tradicional. Já o arquivo project.json contém todas as informações de compilação, dependências e runtimes utilizadas pela aplicação:
{
"Version", "1.0.0- *"
"BuildOptions": {
"DEBUGTYPE": "portable", // reports will be generated if debugging information
"EmitEntryPoint": true // tells whether the module contains an entry for the MAIN method
},
"Dependencies": {}, // informs the project dependencies
"Frameworks": {
"Netcoreapp1.0": {// tells you what is the application framework
"Dependencies": {
"Microsoft.NETCore.App": {// use the super set that contains the .NET Standard Library and standard library
"Type": "platform", // tells the machine framework will be used
"Version", "1.0.1"
}
},
"Imports": "dnxcore50"
}
}
}
O próximo passo é restaurar as dependências, através do comando a seguir, para baixar as bibliotecas NUGET da Internet para o diretório padrão de cache das bibliotecas NUGET (%USERPROFILE%\.nuget\packages\ ou $env:UserProfile\.nuget\packages\). Caso não existir conexão com a internet, o diretório de CACHE será utilizado.
dotnet restore
Após restaurar as bibliotecas, o arquivo project.lock.json é gerado com as referências da aplicação:
{
"Locked": false,
"Version": 2
"Targets": {
".NETCoreApp, Version = v1.0": {
"Libuv / 1.9.0": {
"Type": "package"
"Dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1"
},
"RuntimeTargets": {
"Runtimes / osx / native /_._": {
"AssetType": "native"
"Rid": "osx"
}
}
},
"Microsoft.CodeAnalysis.Analyzers / 1.1.0": {
"Type": "package"
},
"Microsoft.CodeAnalysis.Common / 1.3.0": {
"Type": "package"
"Dependencies": {
"Microsoft.CodeAnalysis.Analyzers" "1.1.0"
"System.AppContext" "4.1.0"
"System.Collections": "4.0.11"
"System.Collections.Concurrent": "4.0.12"
"System.Collections.Immutable" "1.2.0"
// ... And several other references omitted here because of the amount
Para compilar a aplicação utilize o comando:
dotnet build
Por padrão, esse comando irá compilar a aplicação em modo DEBUG. Para compilar em modo RELEASE, utilize o parâmetro:
dotnet build -c release
A aplicação será compilada no diretório a seguir, onde o netcoreapp1.0 representa o framework padrão selecionado (.NET Core):
.\bin\release\netcoreapp1.0\HelloWorldConsole.dll
Para adicionar o FULL .NET Framework (tradicional que faz parte do sistema operacional), adicione a referência "net461", conforme:
{
"Version", "1.0.0- *"
"BuildOptions": {
"DEBUGTYPE": "portable", // reports will be generated if debugging information
"EmitEntryPoint": true // tells whether the module contains an entry for the MAIN method
},
"Dependencies": {}, // informs the project dependencies
"Frameworks": {
"Net461": {},
"Netcoreapp1.0": {// tells you what is the application framework
"Dependencies": {
"Microsoft.NETCore.App": {// use the superset that contains the .NET Standard Library and standard library
"Type": "platform", // tells the machine framework will be used
"Version", "1.0.1"
}
},
"Imports": "dnxcore50"
}
}
}
Ao listar o diretório C:\Temp\HelloWorldConsole\bin\release, observe que existem as seguintes pastas para cada versão do .NET Framework:
- net461
- netcoreapp1.0
Para executar o projeto, digite o seguinte comando:
dotnet run
Para publicar a aplicação, ou seja, empacotar a aplicação e suas dependências em uma pasta, digite o seguinte comando:
dotnet publish -c release
Como eu defini dois frameworks (.NET Core e Full .NET Framework) no project.json, serão publicados dois diretórios para os respectivos frameworks:
- C:\Temp\HelloWorldConsole\bin\release\netcoreapp1.0\publish
- C:\Temp\HelloWorldConsole\bin\release\net461\win7-x64\publish
Observe que no diretório do .NET Framework Full (tradicional - C:\Temp\HelloWorldConsole\bin\release\net461\win7-x64\publish), é gerado o seguinte executável:
HelloWorldConsole.exe
Já o mesmo não ocorre para o diretório do .NET Core (C:\Temp\HelloWorldConsole\bin\release\netcoreapp1.0\publish), onde é gerada a DLL:
HelloWorldConsole.dll
Nesse caso, para que a aplicação seja executada, é necessário utilizar o comando:
dotnet HelloWorldConsole.dll
Isso pode ser explicado através do arquivo project.json, onde o elemento type, da dependência do .NET Core (netcoreapp1.0), está configurado para utilizar o framework da máquina através do elemento "type": "platform" :
"Netcoreapp1.0": {// tells you what is the application framework
"Dependencies": {
"Microsoft.NETCore.App": {// use the superset that contains the .NET Standard Library and standard library
"Type": "platform" , // tells the machine framework will be used
"Version", "1.0.1"
}
},
Para que seja gerado um executável ao invés de uma DLL, de forma que a aplicação seja independente (self-contained) do framework instalado na máquina, é necessário remover o elemento "type": "platform" :
"Netcoreapp1.0": {// tells you what is the application framework
"Dependencies": {
"Microsoft.NETCore.App": {// use the superset that contains the .NET Standard Library and standard library
"Version", "1.0.1"
}
},
Nesse caso, também é necessário adicionar quais serão os runtimes que a aplicação deverá ser compilada, através da tab runtimes. Exemplo para compilar para o Windows e Ubuntu:
{
"Version", "1.0.0- *"
"BuildOptions": {
"DEBUGTYPE": "portable", // reports will be generated if debugging information
"EmitEntryPoint": true // tells whether the module contains an entry for the MAIN method
},
"Dependencies": {}, // informs the project dependencies
"Frameworks": {
"Net461": {},
"Netcoreapp1.0": {// tells you what is the application framework
"Dependencies": {
"Microsoft.NETCore.App": {// use the superset that contains the .NET Standard Library and standard library
"Version", "1.0.1"
}
},
"Imports": "dnxcore50"
}
},
"Runtimes": {
"Win7-x64": {},
"Ubuntu.14.04-x64": {}
}
}
Após salvar a alteração, é necessário restaurar as dependências do projeto:
dotnet restore
Para publicar a aplicação, execute o seguinte comando:
dotnet publish -c release
Observe que agora o executável foi gerado, assim como, todas as dependências da aplicação (incluindo as DLLs do framework) foram adicionadas na pasta publish:
Para reduzir o número de dependências, nós podemos alterar o framework para o "netstandard1.6" que é um subconjunto do netcoreapp1.0(que inclui o NET Core CLR e o .NET Core Library). O framework e as dependências ficariam da seguinte forma:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {
"NETStandard.Library": "1.6.0",
"Microsoft.NETCore.Runtime.CoreCLR": "1.0.2",
"Microsoft.NETCore.DotNetHostPolicy": "1.0.1"
},
"frameworks": {
"netstandard1.6": { }
},
"runtimes": {
"win10-x64": {},
"osx.10.10-x64": {}
}
}
Observe que a quantidade de DLLs foi reduzida para:
Por se tratar de uma aplicação Hello World, é possível reduzir ainda mais a quantidade de dependências:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {
"System.Console": "4.0.0",
"Microsoft.NETCore.Runtime.CoreCLR": "1.0.2",
"Microsoft.NETCore.DotNetHostPolicy": "1.0.1"
},
"frameworks": {
"netstandard1.6": { }
},
"runtimes": {
"win10-x64": {},
"osx.10.10-x64": {}
}
}
Observe que a quantidade de DLLs foi reduzida para:
Espero que tenham gostado.
Referências:
- Getting started with .NET Core on Windows/Linux/macOS using the command line
- Writing .NET Core console apps using the CLI tools: An advanced step-by-step guide
- .NET Core Application Deployment
- Desenvolvendo Aplicações Web Modernas com o ASP.NET Core – Introdução