Showing posts with label Command Line. Show all posts
Showing posts with label Command Line. Show all posts

Sunday, April 16, 2017

How to make a dotnet CLI Tool

Good news, everyone! It is remarkably easy to make a new dotnet CLI (Command Line Interface) tool! I recently created a CLI tool for one of my new projects, Tact.NET RPC, and in this post I will be referencing that project as my example.

The Basics

Step 1) Create your CLI Console App

All you have to do is...

  1. Create a normal .NET Core Console App.
    • NOTE: Currently, the dotnet CLI only supports netcoreapp1.0
  2. Rename the assembly to be prefixed with "dotnet-"
  3. dotnet pack the project and put the package in your local NuGet package source

...that is it! It is literally that easy to create your CLI tool!

Recommendation: use Microsoft.Extensions.Configuration to parse your command line arguments in a standard way.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.0</TargetFramework>
    <AssemblyName>dotnet-tactrpcgen</AssemblyName>
    <PackageId>Tact.Rpc.Generator</PackageId>
    <Version>1.0.3</Version>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="1.1.1" />
  </ItemGroup>
</Project>

Step 2) Consume your CLI Tool NuGet Package

Edit your csproj file and add a DotNetCliToolReference element that references your package.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.6</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Tact.Rpc.Generator" Version="1.0.3" />
  </ItemGroup>
</Project>

Now you are able to invoke your console app via the dotnet command line whenever it is executed in the same path as the csproj.

That's it; it really is that easy!

Development Tips

Here is a simple way to automate the creation and consumption of your CLI tool NuGet package during development.

Sunday, October 25, 2015

Override Configuration via Command Line

In my previous blog posts I have talked about creating complex config objects from your app.config file, as well as how to have cascading configuration settings from multiple files. Now I want to build on that concept by taking in configuration from command line in a generic fashion that will override your other cascading settings.

Configuration Object

public class TestConfig
{
    public string Hello { get; set; }
    public string Goodnight { get; set; }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="TestConfig.Hello" value="World" />
    <add key="TestConfig.Goodnight" value="Moon" />
  </appSettings>
</configuration>

Wednesday, September 30, 2015

XDT Console Application

XML Document Transformations, or XTD, is a great way to transform your app and web config files between environments or builds. It is directly supported by Visual Studio and other third party tools, such as Octopus Deploy.

So how can you transform config files on your own? For starters uou can use great free tools like the Web.config Transformation Tester (which is open source) from AppHarbor.

Would you rather transform your files via command line? Then just do it yourself! Pull down the Microsoft.Web.Xdt package from NuGet, and then copy and paste this code to implement your own simple console app...

Program.cs

namespace XDT
{
  using System;
  using System.IO;
  using System.Text;
  using System.Xml;
 
  using Microsoft.Web.XmlTransform;
 
  public class Program
  {
    private static int Main(string[] args)
    {
      if (args.Length != 3)
      {
        Console.WriteLine("Required Arguments: [ConfigPath] [TransformPath] [TargetPath]");
        return 400;
      }
 
      var configPath = args[0];
      if (!File.Exists(configPath))
      {
        Console.WriteLine("Config not found");
        return 404;
      }
 
      var transformPath = args[1];
      if (!File.Exists(transformPath))
      {
        Console.WriteLine("Transform not found");
        return 404;
      }
 
      try
      {
        var targetPath = args[2];
        var configXml = File.ReadAllText(configPath);
        var transformXml = File.ReadAllText(transformPath);
 
        using (var document = new XmlTransformableDocument())
        {
          document.PreserveWhitespace = true;
          document.LoadXml(configXml);
 
          using (var transform = new XmlTransformation(transformXml, false, null))
          {
            if (transform.Apply(document))
            {
              var stringBuilder = new StringBuilder();
              var xmlWriterSettings = new XmlWriterSettings
              {
                Indent = true,
                IndentChars = "  "
              };
 
              using (var xmlTextWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings))
              {
                document.WriteTo(xmlTextWriter);
              }
 
              var resultXml = stringBuilder.ToString();
              File.WriteAllText(targetPath, resultXml);
              return 0;
            }
 
            Console.WriteLine("Transformation failed for unknown reason");
          }
        }
      }
      catch (XmlTransformationException xmlTransformationException)
      {
        Console.WriteLine(xmlTransformationException.Message);
      }
      catch (XmlException xmlException)
      {
        Console.WriteLine(xmlException.Message);
      }
 
      return 500;
    }
  }
}

Enjoy,
Tom

Real Time Web Analytics