This is a series on the new .Net Core bits.

We can now take everything we have learned and start publishing our applications. Luckily, there is a command for that too.

The Setup

I don't know why I bother saying anything here, this is pretty straight-forward by now.

mkdir mynewapp
cd mynewapp
dotnet new
dotnet restore
dotnet build

And again, we replace the contents of Program.cs. This time, lets try printing a few verses of Dr. Seuss Explaining Computers

using System;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Dr. Seuss Explains Computers");
            Console.WriteLine("============================");
            Console.WriteLine("");
            Console.WriteLine("If a Packet Hits a pocket on a socket on a port, and the bus is interrupted as a very last resort, and the address of the memory makes your floppy disk abort, then the socket packet pocket has an error to report.");
            Console.WriteLine("If your cursor finds a menu item followed by a dash, and the double-clicking icon puts your window in the trash, and your data is corrupted 'cause the index doesn't hash, then the situation's hopeless and your systems gonna crash!");
            Console.WriteLine("");
            Console.WriteLine("");
            Console.WriteLine("Read the rest at: http://computerjokes.net/112.asp");
            Console.WriteLine("");
        }
    }
}

And for good measure another build.

dotnet build

Publishing

To publish our application we use the most obvious of commands:

dotnet publish

Which results in the following file structure.

mynewapp
|-- Program.cs
|-- project.json
|-- project.lock.json
+-- bin
     +-- Debug
          +-- netcoreapp1.0
               |-- mynewapp.deps.json
               |-- mynewapp.dll
               |-- mynewapp.pdb
               |-- mynewapp.runtimeconfig.dev.json
               |-- mynewapp.runtimeconfig.json
               +-- publish
                    |-- mynewapp.deps.json
                    |-- mynewapp.dll
                    |-- mynewapp.pdb
                    +-- mynewapp.runtimeconfig.json

The publish command adds a new build artifact folder - publish. Inside are all of the files for the application to distribute (to someone who has the runtime available). In this case our application is a netcoreapp1.0, so the distribution is the dll, to run with .Net Core runtime.

We can execute our application using the command dotnet mynewapp.dll from inside the publish folder, or from the project folder using a relative path dotnet .\bin\Debug\netcoreapp1.0\mynewapp.dll.

Output folder

We probably want to publish to a different location, so we can use the option -o <OUTPUT_PATH> to publish somewhere else. At the same time, we might use the -c <CONFIGURATION> option to specify a release build.

dotnet publish -o "../Pack/mynewapp" -c Release

Which will give you the following in the Pack folder:

Pack
+-- mynewapp
    |-- mynewapp.deps.json
    |-- mynewapp.dll
    |-- mynewapp.pdb
    +-- mynewapp.runtimeconfig.json

Include Files

We can also include extra files into our output folder. For instances lets add a readme.md file beside our program.cs file.

MyNewApp
========

version 1.0.0

This app prints the first verse of a poem.

In our project.json file we can add packageOptions includeFiles properties, to include our readme.md file.

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "publishOptions": {
    "includeFiles": [
      "readme.md"
    ]
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        }
      },
      "imports": "dnxcore50"
    }
  }
}
dotnet restore
dotnet build
dotnet publish -o "C:\dev\publishingapps\Pack\mynewapp" -c Release

Note there is a current(1.0.0/1.0.1) bug that you need to specify the full path to the app for the output path or it will not include included files correctly. https://github.com/dotnet/cli/issues/3951
(This appears to no longer be a problem for the upcoming csproj changes.)

Otherwise, that's how easy it is to include extra files when publishing.

Publishing .Net 4.5.2 applications

Or 4.5, 4.5.1 & 4.6. They all basically follow the same principles.

It all starts with the project.json file. For reality sake, I am going to add to rather then replace the netcoreapp1.0 target.

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "publishOptions": {
    "includeFiles": [
      "readme.txt"
    ]
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        }
      },
      "imports": "dnxcore50"
    },
    "net452": {
    }
  }
}
dotnet restore  
dotnet build  
dotnet publish -o "C:\dev\publishingapps\Pack\mynewappNet452" -c Release -f net452

Your Pack folder should now have two packaged application folders like the following:

Pack
|-- mynewapp
|   |-- mynewapp.deps.json
|   |-- mynewapp.dll
|   |-- mynewapp.pdb
|   |-- mynewapp.runtimeconfig.json
|   +-- readme.md
+-- mynewappNet452
    |-- mynewapp.exe
    |-- mynewapp.pdb
    +-- readme.md

We now have a .Net 4.5.2 exe that we can run anywhere where .Net 4.5.2 has been installed.

One thing missing is an App.Config, which some of your existing applications likely use for useful things like configuration. You can simply add an include with a trasform to map a file called App.Config, with a transformation to the more expected name of %APPNAME%.exe.config.

Add our App.Config file.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <!-- Settings go here, you know how to use them already? -->
  </appSettings>
</configuration>

And modify the net452 section we added earlier to include the file as a build artifact (that way it is available when using dotnet run as well)

    "net452": {
      "buildOptions": {
        "copyToOutput": {
          "mappings": {
            "mynewapp.exe.config": "App.Config"
          }
        }
      }
    }
dotnet restore
dotnet build
dotnet publish

Remember, if you use build, pack, or publish without using -f <framework> you will get all target frameworks included. (And if you use -f and -o together with publish, it will dump the targets' output on top of each other in the same folder. Probably don't do that.)

Lets take one last look at the filetree in the mynewapp project folder:

mynewapp
|-- Program.cs
|-- project.json
|-- project.lock.json
+-- bin
     +-- Debug
          |-- net452
          |   |-- mynewapp.exe
          |   |-- mynewapp.pdb
          |   +-- win7-x64
          |       |-- mynewapp.exe
          |       |-- mynewapp.exe.config
          |       |-- mynewapp.pdb
          |       +-- publish
          |           |--mynewapp.exe
          |           |--mynewapp.exe.config
          |           |--mynewapp.pdb
          |           +--readme.md
          +-- netcoreapp1.0
               |-- mynewapp.deps.json
               |-- mynewapp.dll
               |-- mynewapp.pdb
               |-- mynewapp.runtimeconfig.dev.json
               |-- mynewapp.runtimeconfig.json
               +-- publish
                    |-- mynewapp.deps.json
                    |-- mynewapp.dll
                    |-- mynewapp.pdb
                    |-- mynewapp.runtimeconfig.json
                    +-- readme.md

In our win7-x64 folder, we have the built output targeting .Net 4.5.2 including our app.config file, and inside that folder is a publish folder, which is our publish output, including both the earlier readme.md and the transformed app.config file ready to zip up and distribute as required.

Onward to the finish!

We are almost wrapped up, only one last piece to go, Self-contained Applications. Stay tuned.