Criando uma console application com esteróides com o pacote System.CommandLine
Tags: dotnet, dotnetcore, dotnetframework, consoleapplication
Published: 2023-09-18 03:31:39

---
title: Criando uma console application com esteróides com o pacote System.CommandLine
published: true
description: 
tags: #dotnet #dotnetcore #dotnetframework #consoleapplication
---
Olá devs! Já se pergutaram como os devs criam consoles application bem pomposas como essas do dotnet, cheias de comandos e listagem do que elas fazem? 
![dotnet console application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uh8f6jd5a5e456w23fvf.png)

Então vamos lá começar com o feijão com arroz e criar uma `console application` no visual studio, ou se você prefirir, dá para usar o command line do `dotnet` para isso. Meus exemplos serão no **Visual studio 2022 Community**, mas você pode usar até um bloco de notas com a `dotnet tool` que funcionará.

## Criando a console aplication

- crie um novo projeto do tipo console application.
![Criando um novo projeto console no visual studio 2022](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymr8rfdjwi6z14d4zomy.png)

- Após sua criação, importe o pacote nuget `System.CommandLine`

![Botão direito do mouse em dependencias do projeto, selecionando Manager Nuget Package](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yalhv1xf0sqhm9hzx75w.png)

Na barra de procura, procure por `System.CommandLine`, mas não se esqueça de marcar a opção `include prerelease`. E então click em **install** para instalar a dependência no seu projeto.

![Busca por System.CommandLine e selecionando include prerelease](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p1al3z0y16x6n3rzl4o.png)

- Agora substitua o código inicial da sua `Program.cs` pelo codigo abaixo:

```C#
using System.CommandLine;

// Crie uma descrição que será exibida caso o usuario não passe nenhum argumento.
// Isso também serve para você escrever uma descrição da sua ferramenta console.
var description = @"
Bem vindo ao meu console charmosão com vários 
comandos listados e documentados";

var rootCommand = new RootCommand(description);

// Criando um argumento a ser aceito por nosso app
var mensagemArg = new Argument<string>("Uma Mensagem", "Apenas essa mensagem será exibida");

// adicionando esse argumento no nosso comando principal
rootCommand.AddArgument(mensagemArg);

// Definindo uma ação para quando esse comando for adicionado.
rootCommand.SetHandler((mensagemArgValue) =>
{
   Console.WriteLine(mensagemArgValue); //Apenas exibe a mensagem recebida

}, mensagemArg);

// Passe os argumentos recebidos pela a console aplication para o objeto rootCommand 
// através do seu metódo invoke.
rootCommand.Invoke(args);
```

Agora execute a sua aplicação console 



![Clique em executar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/smlq6ddhykcaz3fm2k5o.png)



e voilá, temos nossa aplicação rodando com a descrição que colocamos


![Exibição do menu do console application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6r8niduf5dwcbialllo.png)

### A keyword `args`
Uma pequena explicação sobre a keyword `args` que passada como parametro na `rootCommand.Invoke(args);`: Todo console application pode aceitar argumentos como parametro inicial, dentro do `C#` ela é recebida através de uma array de strings, esse array de string é identificado quando você executa um comando separando as palavras por espaço.


## Adicionando nossos primeiros argumentos

Essa lib é bem poderosa e conseguimos até mesmo definir quais argumentos são esperados e a ordem que eles devem acontecer, como você pode ver no código abaixo, onde definimos que o primeiro argumento recebido será uma string

```C#
// Criando um argumento a ser aceito por nosso app
var mensagemArg = new Argument<string>("Uma Mensagem", "Apenas essa mensagem será exibida");

// adicionando esse argumento no nosso comando principal
rootCommand.AddArgument(mensagemArg);

// Definindo uma ação para quando esse comando for adicionado.
rootCommand.SetHandler((mensagemArgValue) =>
{
   Console.WriteLine(mensagemArgValue); //Apenas exibe a mensagem recebida

}, mensagemArg);
``` 

Mas também podemos mudar para dizer que receberemos um inteiro (`int`), um double (`double`), um arquivo (`FileInfo`), um diretório (`DirectoryInfo`) e [varios outros tipos](https://learn.microsoft.com/en-us/dotnet/standard/commandline/model-binding).


## Opções para comandos
Também é possível fazer ações como o comando 

`dotnet restore [project.csproj/solution.sln] --build release`

Vamos criar algo semelhante a isso nesse nosso `ConsoleCharmosao`, onde teremos um novo comando chamado `length` que receberá uma string e retornará a quantidade de caracteres contida nela.
Teremos que mudar nosso  Código para chear proximo disso.

```C#
using System.CommandLine;

// Crie uma descrição que será exibida caso o usuario não passe nenhum argumento.
// Isso também serve para você escrever uma descrição da sua ferramenta console.
var description = @"
Bem vindo ao meu console charmosão com vários 
comandos listados e documentados";

var rootCommand = new RootCommand(description);

// Crie um novo comando
var lengthCommand = new Command("length", "Quantidade de caracteres em uma string");

// define nomes alternativos para chamar esse comando
lengthCommand.AddAlias("len");
lengthCommand.AddAlias("l");

// crie novo argumento a 
var lengthArgument = new Argument<string>("string", "string para ser processada");
lengthArgument.SetDefaultValue(string.Empty);

// adicione o novo argumento ao comando
lengthCommand.AddArgument(lengthArgument);

// crie uma nova opção
var lengthOptionRepeat = new Option<int>("--repeat", "Imprime quantas vezes?");
lengthOptionRepeat.AddAlias("-r");
lengthOptionRepeat.SetDefaultValue(1);

// adicione essa opção ao lengthComand
lengthCommand.AddOption(lengthOptionRepeat);

lengthCommand.SetHandler((lengthArgumentValue, lengthOptionRepeatValue) =>
{
    // recendo os valores e processando-os
    for (int i = 0; i < lengthOptionRepeatValue; i++) 
    {
        Console.WriteLine($"{i + 1}. {lengthArgumentValue.Length}");
    }

}, lengthArgument, lengthOptionRepeat); // lembre-se de passar os parametros aqui


// adicionando o length command ao nosso comando principal
rootCommand.AddCommand(lengthCommand);

// Passe os argumentos recebidos pela a console aplication para o objeto rootCommand 
// através do seu metódo invoke.
rootCommand.Invoke(args);
```
Olha só como ficou nosso console após adição desse comando e option na sessão `Commands`


![Listagem de comandos e execuções](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/73h2pfwbt4pop66fhvlh.png)



### Como testar?

Para testar dentro do **visual studio 2022** é possivel definir `lauchSettings.json` onde eu defini abaixo

```json
{
  "profiles": {
    "ConsoleCharmosao": {
      "commandName": "Project"
    },
    "StringLength": {
      "commandName": "Project",
      "commandLineArgs": "length \"minha string\" --repeat 3"
    }
  }
}
``` 

![lauchSettings.json](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqw7znhzb85gez8d4yky.png)

Caso, o `lauchSettings.json` não esteja aprecendo para você, execute as ações abaixo

- Clique nas opções de execução (setinha para baixo), depois click em debug properties
![Indo pra debug properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6hevxf6t20c6x90d8en.png)

Na janela que abriu, selecione o botão de adicionar configuração, e selecione projeto. Após isso, você pode adicionar o comando que deseja executar na hora de rodar o aplicativo.

![Novo comando StringLength adicionado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gwc3s39vo1w0s5wwclh.png)

Agora você capaz de rodar e debugar seu comando direto do visual studio.

## Deploy e execução

Quando você definir suas configurações de publicação, lembresse de definir o `deployment mode` como `Self-contained`.

![Publish profile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7cxrfere32e6m4k395yq.png)


Com o `.exe` publicado, você poderá rodar comandos como `ConsoleCharmosao.exe length "minha string" --repeat 3`

## Obrigado!
 De agora em diante você sabe fazer um console cheio de firulas e comandos utéis e assim ajudar no DX e UX de suas futuras ferramentas. Qualquer duvida deixa nos comentarios, você pode acessar o [código fonte aqui](https://github.com/MarcosCostaDev/ConsoleCharmosao), Me siga no [Github](https://github.com/MarcosCostaDev) e no [Twitter/X](https://twitter.com/MarcosCostaDev).