Jeremy Lindsay

.net core, arduino, IOT

Using .NET Core 2 to read serial data from an Arduino UNO over USB

If you’ve worked with an Arduino and used a Windows development machine, you’ll probably have used the Arduino IDE to deploy code, and used the IDE’s built in serial monitor to read messages back from the Arduino device. And if you want to use these messages in a .NET application, there’s already good support in the .NET Framework – but what about .NET Core?

In this post, I’ll look at how to use VSCode to create an Arduino simple project which writes to a serial port, and deploy this to an Arduino Uno using VSCode. Then I’ll write about how to use the preview NuGet package to read this data using .NET Core. I’ll finish up with some issues I’ve observed.

Note – this article about .NET Core targets Windows 10 32-bit/64-bit editions – this won’t work if you’re targeting ARM devices with Windows 10 IoT Core (i.e. win10-arm). I’ll cover targeting the ARM platform in a later post.

Also, you’ll obviously need an Arduino for this – I’ve found an Arduino UNO is ideal.

This post has two main sections – setting up a example project on an Arduino using VSCode to write data to a serial port, and then how to access this data using a .NET Core application.

Writing data to a serial port with an Arduino

Setting up VSCode for Arduino development

First of all, you’ll need VSCode on your development machine – you can download it from here. I’ll not describe this in detail – it’s pretty much a point and click installer.

You’ll also need the Arduino IDE installed on your machine so VSCode can access the necessary libraries – you can download it from here. Again this is a very straightforward installation.

Next, install the Arduino extension for VSCode. There are great instructions here – but in summary, from VSCode:

  • Hit ‘Ctrl + P’
  • Type:
ext install vscode-arduino

At this point, you’ll have the Arduino extension for VSCode, presently at version 0.2.4.

Create an Arduino project in VSCode which writes to the serial port

From VSCode, you can create a new Arduino project with the following steps:

  • Create a folder on your development machine to hold the Arduino project – I’ve called mine ArduinoSerialExample
  • Open this folder in VSCode.
  • In VSCode, hit ‘Ctrl + Shift + P’ to open the VSCode Command Palette.
  • Type: Arduino: Initialize – VSCode will offer to create a file with extension app.ino.


  • Rename this to ArduinoSerialExample.ino. It’s important that this file (also known as an Arduino sketch) has the same name as the parent directory.
  • At this point, VSCode will ask what Arduino device is being used – I’m using an Arduino UNO, so I selected this from the list.


Your VSCode workspace is now initialised for Arduino development.

  • Update the code in the ArduinoSerialExample.ino file to have the contents shown below.
int i = 0;
void setup(){
void loop(){
  Serial.print("Hello Pi ");

Important tip – if you copy and paste into VSCode, make sure you don’t accidentally copy unexpected unicode characters, as these will cause compiler errors.

  • Now hit ‘Ctrl + Shift + R’ to compile (also known as Verify) the script – if everything works, you should see an output similar to the text below.
[Starting] Verify sketch - ArduinoSerialExample.ino
Loading configuration...
Initialising packages...
Preparing boards...

Sketch uses 1,868 bytes (5%) of program storage space. Maximum is 32,256 bytes.
Global variables use 198 bytes (9%) of dynamic memory, leaving 1,850 bytes for local variables. Maximum is 2,048 bytes.
[Done] Finished verify sketch - ArduinoSerialExample.ino

Test this project works with a real Arduino

There’s a couple of last steps – connecting the physical Arduino to your development machine, and choosing the serial port.

If you look at the bottom right corner of VSCode, you should see that there’s still a prompt to select the serial port (as shown below).


Once I plugged my Arduino UNO into a USB port on my machine, I was able to click on theprompt (highlighted in a red box in the image above), and VSCode prompts me to select a serial port, as shown below.


I selected COM4, and this updates VSCode to show the serial port in the bottom right corner of the screen, as shown below.


I’m now ready to rest the Arduino is writing to the serial port.

I can upload the sketch to the Arduino by hitting ‘Ctrl + Shift + U’ – this will re-compile the sketch and upload it to the Arduino.

Next, hit open the command palette again (by hitting ‘Ctrl + Shift + P’, and type ‘Arduino Open Serial Monitor’, and select the option to open the Serial Monitor from the dropdown list.


The serial monitor opens, and I’m able to see output being logged to the console from the Arduino through the serial port COM4, as shown below.


Accessing the serial port data on a PC using .NET Core

TL:DR; I’ve uploaded the project to GitHub here.

First set up the .NET Core 2 solution – a console project and a .NET Standard 2.0 class library

Create a new project to hold your .NET solution. I like to manage solutions using the command line – I create a solution using the command:

dotnet new sln -n ReadSerialDataFromArduino

Inside this solution folder, create a new .NET Core console project – I do this using the command:

dotnet new console -n ReadFromArduino

Also create a new .NET Standard 2.0 library project inside the solution folder – again, I do this using the command:

dotnet new classlib -n ReadSerialInputFromUSB

Now we can add these two projects to the solution using the commands below

dotnet sln add .\ReadFromArduino\ReadFromArduino.csproj
dotnet sln add .\ReadSerialInputFromUSB\ReadSerialInputFromUSB.csproj

And we can see the projects in the solution using the command below:

dotnet sln list

And this command presents the expected output of:

Project reference(s)

Finally for this section, I want to add the library as a reference to my console application with the command:

dotnet add .\ReadFromArduino\ReadFromArduino.csproj reference .\ReadSerialInputFromUSB\ReadSerialInputFromUSB.csproj

Add the .NET Core System.IO.Ports preview package

The System.IO.Ports package (available here on allows access to the serial port through a .NET Core application. I can add this to my .NET Standard 2.0 class library by navigating into the ReadSerialInputFromUSB directory, and run the command below:

dotnet add package System.IO.Ports --version 4.4.0-preview2-25405-01

So now the project structure is is place – we can add the bits of code that actually do things.

Let’s use C# to list what serial ports are available to us. I’ve created a class in the ReadSerialInputFromUSB project named SerialInformation, and added a static method called GetPorts().

using System;
using System.IO.Ports;
namespace ReadSerialInputFromUSB
    public class SerialInformation
        public static void GetPorts()
            Console.WriteLine("Serial ports available:");
            foreach(var portName in SerialPort.GetPortNames())

And we can access this through the main method in the ReadFromArduino project:

using ReadSerialInputFromUSB;
namespace ReadFromArduino
    class Program
        static void Main(string[] args)

If we build this and run the project (using dotnet build and dotnet run) the output is:

Serial ports available:

This is exactly what we’d expect from earlier, where VSCode identified COM4 as the port being used by the Arduino.

And if we can get the data from the Arduino into a variable and write to the console, we can do that by using the DataReceived event and using the ReadExisting() method on the serial port object, as shown below:

public void ReadFromPort()
    // Initialise the serial port on COM4.
    // obviously we would normally parameterise this, but
    // this is for demonstration purposes only.
    this.SerialPort = new SerialPort("COM4")
        BaudRate = 9600,
        Parity = Parity.None,
        StopBits = StopBits.One,
        DataBits = 8,
        Handshake = Handshake.None
    // Subscribe to the DataReceived event.
    this.SerialPort.DataReceived += SerialPortDataReceived;
    // Now open the port.
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    var serialPort = (SerialPort)sender;
    // Read the data that's in the serial buffer.
    var serialdata = serialPort.ReadExisting();
    // Write to debug output.

I can call this in my console project’s main method using the code below:

static void Main(string[] args)
    var serialInformation = new SerialInformation();

So when I run this console application, the COM4 serial port is opened, and writes whatever it receives to the debug output.

You can see the source code for the Serial.IO.Ports library on GitHub in the CoreFX library, and there’s access to the nightly builds on

This library is great for connecting to (and reading from) serial ports using a .NET Core application running on a Windows x32/x64 machine. However, one issue is this library doesn’t work with ARM – either for Windows 10 IoT Core or for Linux.

Wrapping up

Using the Serial.IO.Ports preview library available on NuGet, it’s possible to read from serial ports using a .NET Core 2 application on a Windows 32-bit/64-bit machine, and I’ve a very simple example of how to do this available on GitHub here. So far there’s not an implementation in the Serial.IO.Ports library which works for ARM architectures, but I’ll look at options for closing this gap in future posts.

About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Cake, Continuous Integration, Raspberry Pi 3, UWP

Deploy a UWP application to a Windows 10 device from the command line with Cake

I’ve wanted to improve my continuous integration process for building, testing and deploying UWP applications for a while. For these UWP apps, I’ve been tied to using VS2017 for build and deploy operations – and VS2017 is great, but I’ve felt restricted by the ‘point and click’ nature of these operations in VS2017.

Running automated tests for any .NET project is well documented, but until relatively recently I’ve not had a really good way to use a command line to:

  • build my UWP project and solution,
  • run tests for the solution,
  • build an .appxbundle file if the tests pass, and
  • and deploy the appxbundle to my Windows 10 device.

Trying to find out what’s going on under the hood is the kind of challenge that’s catnip for me, and this is my chance to share what I’ve learned with the community.

This is part of a series of posts about building and deploying different types of C# applications to different operating systems.

If you follow this blog, you’ll probably know I normally deploy apps to my Raspberry Pi 3, but the principles in here could be applied to other Windows 10 devices, such as an Xbox or Windows Phone.

Step 1 – Create the demo UWP and test projects.

I’ll keep the description of this bit quick – I’ll just use the UWP template in Visual Studio 2017 – it’s only a blank white screen but that’s ok for this demonstration.


I’ve also created an empty unit test project – again the function isn’t important for this demonstration, we just need a project with a runnable unit test.


I’ve written a simple dummy ‘test’, shown below – this is just created for the purposes of demonstrating how Cake can run a Unit Test project written using MSTest:

using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject2
    public class UnitTest1
        public void TestMethod1()

Step 2: Let’s build our project and run the tests using Cake

Open a powershell prompt (I use the package manager console in VS2017) and navigate to the UWP project folder. Now get the Cake bootstrapper script and example Cake build file using the commands below:

Invoke-WebRequest -OutFile build.ps1

Invoke-WebRequest -OutFile build.cake

I edited the build.cake file to have the text below – this script cleans the binaries, restores the NuGet packages for the projects, builds them and runs the MSTests we created.

#tool nuget:?package=NUnit.ConsoleRunner&version=3.4.0

var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");


// Define directories.
var buildDir = Directory("./App3/bin") + Directory(configuration);


    .Does(() =>

    .Does(() =>

    .Does(() =>
      // Use MSBuild
      MSBuild("../App3.sln", settings =>
      // Use XBuild
      XBuild("../App3.sln", settings =>

    .Does(() =>
    MSTest("../**/bin/" + configuration + "/UnitTestProject2.dll");





Cake’s built in benchmarking shows the order in which the tasks are executed

Task Duration 
Clean                  00:00:00.0124995 
Restore-NuGet-Packages 00:00:03.5300892 
Build                  00:00:00.8472346 
Run-Unit-Tests         00:00:01.4200992 
Default                00:00:00.0016743 
Total:                 00:00:05.8115968

And obviously if any of these steps had failed (for example if a test failed), execution would stop at this point.

Step 3: Building an AppxBundle in Cake

If I want to build an appxbundle for a UWP project from the command line, I’d run the code below:

MSBuild ..\App3\App3.csproj /p:AppxBundle=Always /p:AppxBundlePlatforms="x86|arm" /Verbosity:minimal

There’s four arguments have told MSBuild about:

  • The location of the csproj file that I want to target
  • I want to build the AppxBundle
  • I want to target x86 and ARM platforms (ARM doesn’t work on its own)
  • And that I want to minimise the verbosity of the output logs.

I could use StartProcess to get Cake to run MSBuild in a task, but Cake already has methods for MSBuild (and many of its parameters) baked in. For those parameters which Cake doesn’t know about, it’s very easy to use the WithProperty fluent method to add the argument’s parameter and value. The code below shows how I can implement the command to build the AppxBundle in Cake’s C# syntax.

var applicationProjectFile = @"../App3/App3.csproj";
// ...

MSBuild(applicationProjectFile, new MSBuildSettings
        Verbosity = Verbosity.Minimal
    .WithProperty("AppxBundle", "Always")
    .WithProperty("AppxBundlePlatforms", "x86|arm")

After this code runs in a task, an AppxBundle is generated in a folder in the project with the path:


The path and file name isn’t massively readable, and is also likely to change, so I wrote a short method to search the project directories and return the path of the first AppxBundle found.

private string FindFirstAppxBundlePath()
    var files = System.IO.Directory.GetFiles(@"..\", @"*.appxbundle", SearchOption.AllDirectories);
    if (files.Count() > 0)
        return files[0];
        throw new System.Exception("No appxbundle found");

Now that I have the path to the AppxBundle, I’m ready to deploy it to my Windows device.

Step 4: Deploying the AppxBundle

Microsoft have provided a command line tool in the Windows 10 SDK for deploying AppxBundles – this tool is called WinAppDeployCmd. The syntax used to deploy an AppxBundle is:

WinAppDeployCmd install -file "\MyApp.appxbundle" -ip

It’s very straightforward to use a command line tool with Cake – I’ve blogged about this before and how to use StartProcess to call an executable which Cake’s context is aware about.

But what about command line tools which Cake doesn’t know about? It turns out that it’s easy to register tools within Cake’s context – you just need to know the path to the tool, and the code below shows how to add the UWP app deployment tool to the context:

Setup(context => {
    context.Tools.RegisterFile(@"C:\Program Files (x86)\Windows Kits\10\bin\x86\WinAppDeployCmd.exe");

If you don’t have this tool on your development machine or CI box, it might be because you don’t have the Windows 10 SDK installed.

So with this tool in Cake’s context, it’s very simple to create a dedicated task and pull the details of this tool out of context for use with StartProcess, as shown below.

	.Does(() =>
    FilePath deployTool = Context.Tools.Resolve("WinAppDeployCmd.exe");
    var processSuccessCode = StartProcess(deployTool, new ProcessSettings {
        Arguments = new ProcessArgumentBuilder()
    if (processSuccessCode != 0)
        throw new Exception("Deploy-Appxbundle: UWP application was not successfully deployed");

And now we can run our Cake script to automatically build and deploy the UWP application – I’ve pasted the benchmarking statistics from Cake below.

Task                     Duration
Clean                    00:00:00.0821960
Restore-NuGet-Packages   00:00:09.7173174
Build                    00:00:01.5771689
Run-Unit-Tests           00:00:03.2204312
Build-Appxbundle         00:01:09.6506712
Deploy-Appxbundle        00:02:13.8439852
Total:                   00:03:38.0917699

And to prove it was actually deployed, here’s a screenshot of the list of apps on my Raspberry Pi (from the device portal) before running the script…


…and here’s one from after – you can see the UWP app was successfully deployed.


I’ve uploaded my project’s build.cake file into a public gist – you can copy this and chan-ge it to suit your particular project (I haven’t uploaded a full UWP project because sometimes people have issues with the *.pfx file).

Wrapping up

I’ve found it’s possible to build and deploy a UWP app using the command line, and beyond that it’s possible to integrate the build and deployment process into a Cake script. So even though I still create my application in VS2017 – and I’ll probably keep using VS2017 – it means that I have a much more structured and automated integration process.

About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net core, Cake, Raspberry Pi 3

Running a .NET Core 2 app on Raspbian Jessie, and deploying to the Pi with Cake

I’ve managed to get .NET Core apps running on Windows 10 IoT Core, and on Ubuntu 16.04 (and also Ubuntu MATE), but until recently I’d never tried with Raspbian. I’ve read a few posts from people saying that they couldn’t get it to work, and a couple of nights ago I decided to bite the bullet and give it a go.

There’s a good post here on how to get the .NET Core runtime on a Raspberry Pi running Raspbian, and as always, there are a few tricks to getting things running from scratch. To augment this, I’ve created a “Hello World” application template for .NET Core Raspberry Pi on NuGet which I think will make things easier for the community.

At a very high level, the steps to getting a .NET Core 2 app on Raspbian are:

  • Install Raspbian onto an SD card and insert into your Raspberry Pi 3.
  • Set up SSH and test that you can log into your Raspberry Pi from your development machine.
  • Install .NET Core 2 onto the Raspberry Pi.
  • On your development machine, install the Raspberry Pi C# template for dotnet core.
  • Create a new console application using this template.
  • Deploy this application to your Pi running Raspbian using Cake.

I’ll run through each of these steps below.

Install Raspbian onto an SD card and insert into your Raspberry Pi 3

There are already great explanations of how to install the Raspbian OS onto a Raspberry Pi 3 – many people who have a Pi know how to do this already and I don’t really want to just repeat a well understood process here – so I’ve just put some useful links below:

Set up SSH and test that you can log into your Raspberry Pi from your development machine

Once you’ve set up Raspbian and booted your Pi to the desktop, you’ll need to allow SSH connections. These aren’t enabled by default but it’s very easy to configure this.

First open the main Raspberry Pi menu on your desktop as shown in the image below, and open the Preferences sub-menu to reveal the “Raspberry Pi Configuration” option.


Open the “Raspberry Pi Configuration” option screen, and click on the “Interfaces” tab. There’s lots of useful settings here, but the one we want to enable is SSH – click on the “Enabled” radio button as shown below, and then click on OK. SSH is now enabled on your Pi.


You’ll need to find the IP address of your Raspberry Pi – I think the easiest way is to open a terminal on your Pi and type:

hostname -I

This tells me that my Pi has the IP address

Now we need to check you can log in from your development machine. I personally find it’s easiest to use PuTTY to do this. I’ve blogged about installing PuTTY before so I won’t repeat it all here – but a few tips are:

This bit is really important: When you install PuTTY using the installer, it ships with a couple of other programs – pscp.exe and plink.exe, which live in the same directory as putty.exe. You’ll need both of these to deploy the code to the Pi. Pscp.exe allows you to copy files from Windows to Linux, and plink allows you to remotely change permissions on the files you deploy.

It also makes life easier to add the putty installation directory to your machine’s path. If Cake doesn’t know where pscp and plink are on your machine, then you’ll probably see and error about unknown executables during deployment.

So open PuTTY, enter the Pi’s IP address and select the “Connection Type” to be SSH, as shown below:


When you click Open, a command prompt should open where you can type the username and password for the Pi 3.


The default username and password combo for Raspbian is “pi” and “raspberry“, and you should change the default password as soon as possible.

Install .NET Core 2 onto the Raspberry Pi

There’s a straightforward set of commands that you can run through PuTTY to install .NET Core 2 onto your Pi running Raspbian – I’ve written them below:

# Update the Raspbian Jessie install
sudo apt-get -y update

# Install the packages necessary for .NET Core
sudo apt-get -y install libunwind8 gettext

# Download the nightly binaries for .NET Core 2

# Create a folder to hold the .NET Core 2 installation
sudo mkdir /opt/dotnet

# Unzip the dotnet zip into the dotnet installation folder
sudo tar -xvf dotnet-runtime-latest-linux-arm.tar.gz -C /opt/dotnet

# set up a symbolic link to a directory on the path so we can call dotnet
sudo ln -s /opt/dotnet/dotnet /usr/local/bin

Now you can test this install by running the dotnet –info command to see the version installed on Raspbian.


On your development machine, install the Raspberry Pi C# template

Now that we have .NET Core 2 installed on our Raspbian, we can go back to our development machine to create an application to run on the Pi.

First, install the template for creating Raspberry Pi applications

 dotnet new -i RaspberryPi.Template::*

This will create a new template available to dotnet core – you can list them all with the command:

dotnet new --list

And in the screenshot below, you can see there is now a new template called “Empty .NET Core IoT Project”, highlighted in red below.


Create a new console application using this template

It’s really easy to create a new console application now – just run the command below (obviously my application is called “HelloRaspbian”, but yours could be something different):

dotnet new coreiot -n HelloRaspbian

When you browse to this new application folder using your preferred development tool (mine is VSCode), you’ll see some files – we need to make a couple of changes.

First, run the command below to pull down the latest Cake build PowerShell file:

Invoke-WebRequest -OutFile build.ps1

This command is also in the README.txt file which comes packaged with the application.

Now, open the build.cake file and you’ll see some defaults at the top of the file:

// ARGUMENTS (WITH DEFAULT PARAMETERS FOR LINUX (Ubuntu 16.04, Raspbian Jessie, etc)
var runtime = Argument("runtime", "linux-arm");
var destinationIp = Argument("destinationPi", "<>");
var destinationDirectory = Argument("destinationDirectory", @"<>");
var username = Argument("username", "<>");
var executableName = Argument("executableName", "HelloRaspbian");

Replaced those placeholders with the correct environment variables – I’ve shown my own settings below:

// ARGUMENTS (WITH DEFAULT PARAMETERS FOR LINUX (Ubuntu 16.04, Raspbian Jessie, etc)
var runtime = Argument("runtime", "linux-arm");
var destinationIp = Argument("destinationPi", "");
var destinationDirectory = Argument("destinationDirectory", @"/home/pi/DotNetConsoleApps/RaspbianTest");
var username = Argument("username", "pi");
var executableName = Argument("executableName", "HelloRaspbian");

I’ve created a folder on the Pi to deploy my application to, using the command below at the PuTTY SSH prompt at my home directory (/home/pi/).

mkdir -p DotNetConsoleApps/RaspbianTest

Deploy this application to your Pi running Raspbian using Cake

Once I’ve replaced the placeholders in my Cake file, the only thing left to do is run the build.ps1 file from a PowerShell prompt.


To test this, go back to the PuTTY SSH prompt and navigate to your home directory and run:


And you’ll get a text output saying “Hello Internet of Things!”


Wrapping up

I hope this post is useful to anyone trying to get a C# console application running on Raspbian. I think Raspbian is the default OS for Raspberry Pi users, so this should open up many development opportunities. My Raspberry Pi template makes creating the default console application easier, and Cake is a brilliant way to orchestrate the deployment process (rather than dragging and dropping files using tools like WinSCP, and having to change file permission manually). I’ll be blogging more on the future on deploying IoT applications to this platform.

I’ve written a few posts now about how to deploy C# Raspberry Pi applications to Windows 10 IoT Core, Ubuntu, and Raspbian (all using Cake as the orchestration tool) – next time I’ll write about how to use Cake to automatically build a UWP AppxBundle and deploy that AppxBundle to Windows 10 IoT Core.

About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Cake, Performance

Calling a custom executable from Cake using StartProcess and ProcessSettings

I’ve previously written about how I’ve used Cake to orchestrate my build and deployment processes, and write the code for these processes in C# rather than PowerShell. This time I’ll write about how I’ve improved the speed of my deployment process by using custom tools which aren’t yet built into Cake.

Some background about my deployment process

A common part of a deployment process is copying files repetitively from a source to a destination, and Cake provides a good way to do this – the CopyFiles static method.

To use this, we just need to specify the source directory, the remote destination directory, and plug these in as parameters. I’ve written some sample code below showing how a “Deploy” task might move an application from a “publish” directory to a remote machine.

    .Does(() =>
	// The files I want to copy are in the publish directory - I use the
	// wildcard character to specify that I want to copy everything
	var source = @".\publish\*";
	// The destination is on my local network and accessible on the path below
	var destination = @"\\\c$\ConsoleApps\DeployedApplication";
	// Now just plug in the source, destination
	// The boolean parameter ensures we preserve the folder structure
	CopyFiles(source, destination, true);

This works well, but it also copies across every file, every time – it doesn’t matter whether the file has changed or not – and this the slowest part of my deployment process.  I would prefer to mirror my source and destination files, and only copy across files that have changed. This would speed up deployments across my local network.

Using RoboCopy to mirror directory structures

Microsoft have created a command line file copy utility which allows me to copy or mirror directory structures called RoboCopy (Robust File Copy) – it’ll only copy the files/directories that have changed, and this sounds like exactly what I need.

In copying files from source to destination, I’ve chosen the word “mirror” because RoboCopy needs to be passed a switch “/MIR”, which is short for mirror. From Microsoft’s TechNet documentation:

/MIR is an option to ROBOCOPY where you mirror a directory tree with all the subfolders including the empty directories and you purge files and folders on the destination server that no longer exists in source.

The command I’d need to mirror files has the format:

robocopy /MIR source_directory destination_directory

And to copy from my source directory


to the destination on the C drive of a machine with IP address


I just need to plug these values as arguments to the robocopy executable, as shown below:

robocopy /MIR ".\publish\" "\\\c$\ConsoleApps\DeployedApplication"

But how can I use RoboCopy with Cake?

Turns out it’s quite easy with a few things in Cake which can help us.

  • We can use the StartProcess method – I can pass in executable that I want to run (i.e. robocopy.exe), and I can also pass in the arguments for this executable.

I don’t need to pass in the full path to the executable because robocopy.exe is in a folder which is in my machine’s path, i.e. C:\Windows\System32

  • I can also clean up my code a little by keeping this code in its own method in the file.
private void MirrorFiles(string source, string destination)
    StartProcess("robocopy", new ProcessSettings {
        Arguments = new ProcessArgumentBuilder()

Now I can adjust the Task shown previously (i.e. “Deploy”) to use this method instead:

    .Does(() =>
	// The files I want to copy are in the publish directory
	var source = @".\publish\";
	// The destination is on my local network and accessible on the path below
	var destination = @"\\\c$\ConsoleApps\DeployedApplication";
	// Now just plug in the source, destination
	MirrorFiles(source, destination);

What practical difference does this make?

In my application’s Cake build script, there’s very little difference – a new method to mirror files, and a slight change to a task to copy (or mirror) files across a network.

But the real advantage comes when we look at the time taken to deploy my application.

Another nice feature of Cake is that it writes out the time taken by each task which helps with performance benchmarking.

I’ve pasted the timings for each stage of my original deployment process below for when I just copy files instead of using robocopy:

Task                  Duration 
Clean                 00:00:00.2378497 
Restore               00:00:03.9107662 
Build                 00:00:05.2128133 
Publish               00:00:08.0715728 
Deploy                00:00:43.1527382 
Default               00:00:00.0021827 
Total:                00:01:00.5879229

Notice it took 43 seconds to deploy my application’s files from source to destination – approximately 75% of the total time. And everytime I change my application and re-deploy, the time taken to carry out this operation is approximately the same, copying across files that have changed and also those that haven’t changed.

Let’s change the script to mirror files using robocopy (i.e. only copy across files that have changed since the last build) rather than just copying all files – I’ve pasted the new timings below:

Task                  Duration 
Clean                 00:00:00.2661543 
Restore               00:00:02.7529030 
Build                 00:00:04.7478403 
Publish               00:00:06.3981560 
Deploy                00:00:00.6685282 
Default               00:00:00.0033186 
Total:                00:00:14.8369004

It has gone from copying every file in 43 seconds to just copying 5 files that changed in 0.66 seconds – this is a huge difference for me, making it much quicker and more convenient for me to make an application, change, build and deploy to my test rig.

Wrapping up

In this post I wanted to share with the community how flexible Cake is by demonstrating how I’ve used Robocopy to speed my up deployments.

  • I’ve been able to switch out Cake’s built in copying feature, and instead use a local executable (that isn’t a core part of Cake or an addin) by passing it to the StartProcess method.
  • I’ve been able to write a private method in my C# script to keep the code clean.
  • Finally I’ve been able to use Cake’s default output to benchmark performance before and after my change.

Being able to extend the core features in Cake with StartProcess is really powerful – it’s not quite as re-useable as building a dedicated add-in, but it can still allow us to quickly customise and optimise build scripts.

About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Troubleshooting, Xamarin

Troubleshooting the default install of Xamarin with Visual Studio 2017 and Windows 10 Creators Update

Since I’ve recently started using Xamarin for cross platform development, I thought it would be nice to share with the community how I’ve got past some of the issues which tripped me up for a while when I was becoming familiar with it. This isn’t really a normal “getting started with Xamarin” tutorial – there’s lots of them already out there already, like this one – but hopefully anyone starting off with Xamarin will find it useful.

I use Windows 10 (and have installed the Creator’s Update) – this allows me to use Xamarin.Forms. You’ll know if you’re on the Creator’s Update version if your Windows build number is 1703. If you’re on a different version of Windows, you might have different experiences to me (you can check your version by going to Windows Settings -> System -> About).

Before we begin – what’s Xamarin and why should I use it?

With Xamarin tools built into Visual Studio, developers can create native applications in C# for Windows, Mac and Linux devices. So instead of writing and managing three different codebases for three different platforms, developers can just write their code once and deploy it to different app-stores.

Installing Xamarin tools for Visual Studio 2017

With Visual Studio 2017, it’s very easy just open up the setup wizard, select the Xamarin tools (as shown below) and just wait for it to install.


It’s probably going to take a long time to install VS2017 with Xamarin – adding Xamarin to the base Visual Studio install makes it about 25GB bigger.

Tip: If you leave your machine to download and install Xamarin, it’s worth adjusting your power settings to make sure an unattended machine doesn’t switch off in the middle of the download – like mine did the first time (facepalm).

Creating a project with the default Xamarin template

This bit is straightforward to anyone who’s created a new project in Visual Studio 2017 before.

Select File -> New Project to open the dialog below, and choose a name for the project:


After clicking OK on the dialog above (which chooses a Cross Platform App project type), the dialog will close and open a new project. I chose to use Xamarin.Forms (which allows developers to create cross platform user interfaces). I also chose to create a Shared Project because I only expect my code to be used in my application, rather than shared with other developers as a Portable Class Library (you can read more about the differences between Shared Projects and Portable Class Libraries here).


When you click OK, the project and files will be created, and a window like the one below will appear with instructions for setting up the Mac Agent. (I don’t have a Mac and I’d need Visual Studio Enterprise to use this anyway, so I normally click on the “Don’t show this again” box in the bottom left corner).


Finally you’ll be prompted for the versions of Windows that you want the UWP flavour of your project to target. I normally just click OK here.


At this point, you’ll have a simple Xamarin solution in Visual Studio 2017, which contains 4 projects – one for iOS, one for Android, one for UWP, and one shared project.

Also notice that there is one file open in VS2017 after you create the solution – App.xaml.cs in the shared project. I’ll explain why this is relevant later.

And now for the gremlins ex machina

After this point, I hit a few snags. Things I wanted to do that didn’t work out of the box for me were:

  • Compile the application without error or warnings
  • Run the application in a Windows Phone Emulator
  • Run the application in an Android Emulator

I’ll run through some of the symptoms of problems I encountered trying the things above, and how I fixed them.

Compiling the solution led to multiple warnings and errors

Tip: Prepare to wait a while when building the solution for the first time – it needs to download a lot of NuGet packages.

Unfortunately my attempt to compile the project out of the box showed an error in the UWP project and a bunch of warning messages for the Android project.

Getting rid of the error CS0103 –  ‘InitializeComponent’ does not exist in the current context

The error reports “The name ‘InitializeComponent’ does not exist in the current context.”


I eventually noticed a couple of things that seemed a bit bizarre:

  • Even though I have an error, the message in the status bar in the bottom left reports “Rebuild All succeeded” – both can’t be right surely?
  • This error relates to the App.xaml.cs file which is open in the editor panel. When I opened Main.xaml.cs from the Shared Project in the VS2017 editor, I now see two errors (as shown in the image below).


So these errors don’t seem to negatively affect the build, and if I really want to get rid of them, I can just close those files which gets rid of the errors (as shown below).


Getting rid of warnings about $(TargetFrameworkVersion) mismatches

Three of the warnings I saw were very similar:

The $(TargetFrameworkVersion) for Xamarin.Forms.Platform.dll (v7.1) is 
greater than the $(TargetFrameworkVersion) for your project (v6.0). 
You need to increase the $(TargetFrameworkVersion) for your project.

The $(TargetFrameworkVersion) for Xamarin.Forms.Platform.Android.dll (v7.1) 
is greater than the $(TargetFrameworkVersion) for your project (v6.0). 
You need to increase the $(TargetFrameworkVersion) for your project.

The $(TargetFrameworkVersion) for FormsViewGroup.dll (v7.1) is greater 
than the $(TargetFrameworkVersion) for your project (v6.0). 
You need to increase the $(TargetFrameworkVersion) for your project.

The warning says I need to increase the TargetFrameworkVersion for my Android project, but when I look at the properties for this project, I actually can’t increase it past version 6 (MarshMallow).


Fortunately we’re not at a dead end here – we can go to the Start Menu, and search for the “SDK Manager” for Android, which is installed with the Xamarin component of Visual Studio 2017 (shown below).


Tip: Run the Android SDK Manager as administrator by right-clicking on the shortcut and select “More -> Run as administrator”. If you don’t run as administrator, you might get an error later when the program tries to create a temporary folder for downloads.

When I start the Android SDK Manager, it analyses the packages presently installed, and advises what needs to be updated. On my system, 10 packages needed to be installed or updated, as shown below.


When I click on the “Install 10 packages…” button, another window appears asking me to accept the licence. I accepted the licence and clicked on “Install”.


The installation and update procedure starts – this can take a few minutes.


Once it’s finished installing, let’s return to Visual Studio 2017  –  I restarted it, and then cleaned and rebuilt the solution. This time the warnings about $(TargetFrameworkVersion) mismatches are gone.

Getting rid of warning IDE0006 – “Error encountered while loading the project”

I sometimes found that I had a warning IDE0006 which advised “Error encountered while loading the project. Some project features, such as full solution analysis for the failed project and projects that depend on it, have been disabled“.


This usually happened just after I created a project, and I found that if I close VS2017, restart it, and re-open and rebuild the solution the warning disappears.

So to summarise, in order to compile the default project without errors or warnings:

  • Run the Android SDK manager as administrator, and install/update the recommended packages.
  • Restart Visual Studio 2017 and re-open the project.
  • Close all files from the shared project which have the type *.xaml.cs.

Running in your application in the Windows Phone Emulator

Tip: If you want to run your application in an emulator, you’ll definitely need a 64-bit machine which allows hardware virtualisation. Your machine will also need to be pretty powerful, or you might find running an emulator to be unbearably slow.

I found this to be straightforward as soon as I installed a Windows Phone emulator.

If you don’t have any Windows Phone emulators installed, you can grab some from here:

I changed the start-up project to the UWP project, and changed the debugging target to be one of the Windows Phone Mobile emulators.


After hitting play (or F5) to start running the Windows UWP application in a Windows Phone emulator, I was prompted to set my machine into Developer mode to allow me to load apps – I just had to select the third option (“Developer mode”) as shown in the image below (you can access this screen from Start -> Settings -> For developers).


But after changing this setting, everything worked well – no gremlins here. The phone emulator starts up after a couple of minutes, and I was easily able to see the Xamarin application in the list of apps installed to the phone emulator.


And when I run the Xamarin app in the emulator, I see the correct result – a simple form with a message saying “Welcome to Xamarin Forms!”


Running your application in the Android Emulator

Visual Studio 2017 comes packaged with several Android Emulators – you can see them if you change the target project to the Android one, and look at the dropdown list on its right.


Tip: I never use either the two emulators which target ARM. I have never managed to successfully deploy a project to one of these emulators, even with a reasonably powerful machine.

If you don’t believe me, Visual Studio even gives you a warning if you try to use them:screenshot.25

It’s much, much faster to target one of the emulators which targets x86.

Use the Android x86 emulator – but you need to turn Hyper-V off

You don’t need to uninstall Hyper-V to run the Android x86 emulator on Windows 10 – you just need to turn it off. The command to do this is very simple from a command prompt running as administrator:

bcdedit /set hypervisorlaunchtype off

Reboot for this setting change to take effect.

Of course it might not suit you to turn Hyper-V off on your machine – and another alternative is to deploy to an actual Android device – there’s some great instructions for this here:

My experience was that I couldn’t successfully start and deploy my project to an Android emulator from Visual Studio 2017. However, I was able to start the Android emulator from the Android AVD Manager, available from the start menu (as shown below).


When you start this program, you’ll see a dialog like the one below which lists the Android Virtual Devices available on your development machine.


Select one of the x86 emulators, and click on the “Start…” button. Accept the default options on the launch screen, and an Android phone emulator will start.


Now go back to Visual Studio 2017. Select the emulator which you’ve just started in the drop down list on the right of the green “Play” arror. Now right click on the Android project, and select “Deploy Solution”.

This should now deploy the Xamarin application to the Android emulator, as shown below (our app is in the top row, second column):


And when we click on the Xamarin application icon in the emulator, as expected we see the same screen as in the Windows Phone emulator which says “Welcome to Xamarin Forms!”


Wrapping up

This was just a quick post to help other Xamarin developers who are starting out avoid some of the headaches I had. And just to be really clear, I’m not criticising Xamarin or Visual Studio – getting code to work on 3 different platforms which are constantly changing and updating is pretty miraculous, and ultimately the things I had to do weren’t that big a deal to change.

There are already a few troubleshooting guides from Microsoft on Xamarin like this one. The tips below are things I didn’t find covered anywhere else.

  • Sometimes errors (for example, CS0103) are mis-reported by VS2017 for files which are open in the editor, particularly *.xaml.cs files from the Shared Project – try closing these files and rebuilding to see if the errors go away.
  • Other warnings appear after the project is first created (for example, IDE0006), but if you restart VS2017 and re-build the project, the warning disappears.
  • Opening the Android SDK Manager as administrator and updating the libraries you have on your development machine can help to remove warnings related to TargetFrameworkVersion mismatches – remember to restart VS2017 after the update, and then clean and rebuild your solution through VS2017.
  • Don’t use the Android ARM emulators on Windows 10 – instead start an x86 emulator from the Android AVD manager, and deploy from VS2017 to the emulator which is running.
  • If the x86 emulator won’t start, you might need to disable Hyper-V using the command “bcdedit /set hypervisorlaunchtype off“.

About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, .net core, Raspberry Pi 3

Automating .NET Core deployments to different platforms with Cake

Recently I’ve been using Cake to automate code deployments to Windows and Ubuntu devices.

Since .NET Core 2 became available, I’ve been able to write C# applications to work with devices which can host different operating systems – specifically the Raspberry Pi, where I’ve been targeting both Windows 10 IoT Core and Ubuntu 16.04 ARM.

I can deploy my code to hardware and test it there because I own a couple of Pi devices – each running one of the operating systems mentioned above. Each operating system requires code to be deployed in different ways:

  • The Windows 10 IoT Core device just appears on my home workgroup as another network location, and it’s easy to deploy the applications by copying files from my Windows development machine to a network share location.
  • For Ubuntu 16.04 ARM, it’s a bit more complicated – I need to use the PuTTY secure client program (PSCP) to get files from my Windows development machine to the device running Ubuntu, and then use Plink to make application files executable.

But I’ve not really been happy with how I’ve automated code deployment to these devices. I’ve used Powershell scripts to manage the deployment – the scripts work fine, but I find there’s a bit of friction when jumping from programming C# to Powershell, and some of dependencies between scripts are not really intuitive.

It’s also a bit difficult to explain to people how to use the scripts, and that’s always a sure sign of a code smell.

Recently I’ve found a better way to manage my build and deployment tasks. At my local .NET user group, we had a demonstration of Cake which is a tool that allows me to orchestrate my build and deployment process in C#. It looked like it could help remove some of my deployment issues – and I’ve written about my experiences with it below.

Getting started

There’s lots more detail on how to get started in the website here, but I’ll run through the process that I followed.

Create a project

I’ve previously created a simple project template for a Raspberry Pi which is in a custom nuget package (I’ve written more about that here). You can install the template from nuget by running the command below.

dotnet new -i RaspberryPi.Template::*

This creates a simple hello world application targeting the .NET Core 2 framework.

dotnet new coreiot -n SamplePi

You don’t have to create a project for a Raspberry Pi to follow along with this post – you could just use the regular dotnet command for a new console project:

dotnet new console -n HelloWorld

Create the bootstrapper script

After the project was created, I opened the project folder in VSCode, opened the Powershell terminal, and ran the code below.

Invoke-WebRequest -OutFile build.ps1

This creates a new file in the root of my project called “build.ps1“. It won’t do anything useful yet until we’ve defined our build and deployment process (which we’ll do in the next few sections) – but this bootstrapping script takes care of lots of clever things for us later. It verifies our build script compiles, and it’ll automatically pull down any library and plugin dependencies we need.

Create a Cake build script

The build script – called build.cake – will contain all of the logic and steps needed to build and deploy my code. There’s already an example repository on GitHub which has a few common tasks already. Let’s use the script in that sample repository as our starting point and download it to our project using the PowerShell script below.

Invoke-WebRequest -OutFile build.cake

At this point, if you’re using VSCode, your project should look something like the image below.


Once you’ve loaded the example project’s build script – you can see it here – there’s a few things worth noting:

  • The build script uses C# (or more specifically, a C# domain specific language). This means there’s less friction between creating functional code in C# and orchestrating a build and deployment process in Cake. If you can write code in C#, you’ve got all the skills necessary to build and deploy your code using Cake.
  • Each section of the build and deployment process is nicely separated into logical modules, and it’s really clear for each step what tasks need to complete before that step can start. And because the code written in a fluent style, this means that clarity is already baked into the code.
  • The script shows how we can process arguments passed to the build script:
var target = Argument("target""Default");

The Argument method defines a couple of things:

  1. “target” is the name of the parameter passed to the build.ps1 script
  2. “Default” is the value assigned to the C# target variable if nothing is specified.

So we could get our build script to use something different to the default value using:

.\build.ps1 -target Clean // this would run the "Clean" task in our script, and all the tasks it depends on.

Customizing the build.cake script

Of course this build.cake file is just a sample to help me get started – I need to make a few changes for my own .NET Core 2 projects.

The build and deployment steps that I need to follow are listed below:

  • Clean the existing binary, object and publish directories
  • Restore missing nuget packages
  • Build the .NET Core code
  • Publish the application (targeting Windows or Ubuntu operating systems)
  • Deploy the application (targeting Windows or Ubuntu operating systems)

I’m going to write a different Cake task for each of the steps above.

Modify the build.cake script to clean the build directories

This is a very simple change to the existing build.cake file – I can specify the binary, object and publish directories using C# syntax, and then make a minor change to the task called “Clean” (which already exists in the build.cake file we created earlier).

var binaryDir = Directory("./bin");
var objectDir = Directory("./obj");
var publishDir = Directory("./publish");

// ...
    .Does(() =>

Modify the build.cake script to restore missing nuget packages

Again, there’s a task already in the build.cake file which could do this job for us called “Restore-nuget-packages”. This would work, but I’d like to clearly signal in code that I’m using the normal commands for .NET Core projects – “dotnet restore”.

DotNetCoreRestore is a method built into Cake (see the source code here).

I created the C# variable to hold the name of my project (csproj) file, and can call the task shown below.

var projectFile = "./SamplePi.csproj";

// ...
    .Does(() =>

Notice how I’ve specified a dependency in the code, which requires that the “Clean” task runs before the “Restore” task can start.

Modify the build.cake script to build the project

The methods that Cake uses to restore and build projects are quite similar – I need to specify C# variables for the project file, and this time also what version of the .NET Core framework that I want to target. Of course this task depends on the “Restore” task we just created – but notice that we don’t need to specify the dependency on “Clean”, because that’s automatically inferred from the “Restore” dependency.

We also need to specify the framework version and build configuration – I’ve specified them as parameters with defaults of “.netcoreapp2.0” and “Release” respectively.

var configuration = Argument("configuration""Release");
var framework = Argument("framework""netcoreapp2.0");

// ...
    .Does(() =>
        var settings = new DotNetCoreBuildSettings
            Framework = framework,
            Configuration = configuration,
            OutputDirectory = "./bin/"
        DotNetCoreBuild(projectFile, settings);

Modify the build.cake script to publish the project

This is a little bit more complex because there are different outputs depending on whether we want to target Windows (the win10-arm runtime) or Ubuntu (the ubuntu.16.04-arm runtime). But it’s still easy enough to do this – we just create an argument to allow the user to pass their desired runtime to the build script. I’ve decided to make the win10-arm runtime the default.

var runtime = Argument("runtime""win10-arm");

// ...
    .Does(() =>
        var settings = new DotNetCorePublishSettings
            Framework = framework,
            Configuration = configuration,
            OutputDirectory = "./publish/",
            Runtime = runtime
        DotNetCorePublish(projectFile, settings);

Modify the build.cake script to deploy the project to Windows

I need to deploy to Windows and Ubuntu – I’ll consider these separately, looking at the easier one first.

As I mentioned earlier, it’s easy for me to deploy the published application to a device running Windows – since the device is on my network and I know the IP address, I can just specify the IP address of the device, and the directory that I want to deploy to. These can both be parameters that I pass to the build script, or set as defaults in the build.cake file.

var destinationIp = Argument("destinationPi""");
var destinationDirectory = Argument("destinationDirectory"@"c$\ConsoleApps\Test");
// ...
    .Does(() =>
        var files = GetFiles("./publish/*");
        var destination = @"\\" + destinationIp + @"\" + destinationDirectory;
        CopyFiles(files, destination, true);

Modify the build.cake script to deploy the project to Ubuntu

This is a bit more complex – remember that deploying from a Windows machine to an Ubuntu machine needs some kind of secure copy program. We also need to be able to modify the properties of some files on the remote device to make them executable. Fortunately a Cake add-in already exists which helps with both of these operations!

There are hundreds of add-ins for Cake – you can find more of them here and search the API here.

First, let’s structure the code to differentiate between deployment to a Windows device and deployment to an Ubuntu device. It’s easy enough to work out if we’re targeting the Windows or Ubuntu runtimes by looking at the start of the runtime passed as a parameter. I’ve written the skeleton of this task below.

    .Does(() =>
        var files = GetFiles("./publish/*");
        if (runtime.StartsWith("win"))
            var destination = @"\\" + destinationIp + @"\" + destinationDirectory;
            CopyFiles(files, destination, true);
            // TODO: logic to deploy to Ubuntu goes here

I found an add-in for securely copying files called Cake.Putty – you can read more about the Cake.Putty library on Github here.

All we need to do to get Cake to pull the necessary libraries and tools is add one line to our build.cake script:

#addin "Cake.Putty"

That’s it – we don’t need to explicitly start any other downloads, or move files around – it’s very similar to how we’d include a “using” statement at the top of a C# class to make another library available in the scope of that class.

So next we want to understand how to use this add-in – I’ve found there’s good documentation on how to use the methods available in the plugin’s GitHub repository here.

From the documentation on how to use the PSCP command in the add-in, I need to pass two parameters:

  • a string array of file paths as the first parameter, and
  • the remote destination folder as the second parameter.

The second parameter is easy, but the first one is a bit tricky – there’s a function built into Cake called GetFiles(string path) but this returns an IEnumerable collection, which obviously is different to a string array – so I can’t use that.

But this is a great example of an area where I’m really able to take advantage of being able to write C# in the build script. I can easily convert the IEnumerable collection to a string array using LINQ, and pass this as the correctly typed parameter.

var destination = destinationIp + ":" + destinationDirectory;
var fileArray = files.Select(m => m.ToString()).ToArray();
Pscp(fileArray, destination, new PscpSettings
        SshVersion = SshVersion.V2,
        User = username

So now the deployment code has a very clear intent and easily readable to a C# developer – a great advantage of using Cake.

Finally, I can use Plink (also available in the Cake.Putty add-in) to make the application executable on the remote machine – again we need to specify the file to make executable, and the location of this file, which is straightforward.

var plinkCommand = "chmod u+x,o+x " + destinationDirectory + "/SamplePi";
Plink(username + "@" + destination, plinkCommand);

So now our deployment task is written in C#, and can deploy to Windows or Ubuntu devices, as shown below.

    .Does(() =>
        var files = GetFiles("./publish/*");
        if (runtime.StartsWith("win"))
            var destination = @"\\" + destinationIp + @"\" + destinationDirectory;
            CopyFiles(files, destination, true);
            var destination = destinationIp + ":" + destinationDirectory;
            var fileArray = files.Select(m => m.ToString()).ToArray();
            Pscp(fileArray, destination, new PscpSettings
                    SshVersion = SshVersion.V2,
                    User = username
            var plinkCommand = "chmod u+x,o+x " + destinationDirectory + "/SamplePi";
            Plink(username + "@" + destination, plinkCommand);

I’ve noticed that this add-in doesn’t handle file paths which have spaces in them – but it works if the full file path has no spaces.

One last thing – I’ve included the parameters for a Windows deploy all the way through this post – however, if I wanted to change these, I could override the defaults by passing them to the ScriptArgs switch using a command like the one below:

       -ScriptArgs '--runtime=ubuntu.16.04-arm', 
      -target Publish

I can pass values to the “-target” and “-configuration” parameters directly because they’re explicitly mentioned in the build.ps1 script – the rest have to be passed as a comma separated list of name-value pairs to the “-ScriptArgs” parameter. There’s a bit more on passing parameters to the build script on StackOverflow here.

I’ve pushed my new deployment scripts to GitHub here and the rest of this sample project to here.

Wrapping up

Cake allows me to write my build and deployment scripts in C# – this makes it much easier for developers who are familiar with C# to write automated deployment scripts. It also makes the dependencies between tasks really clear.

I’m much happier using this deployment mechanism rather than the one I had previously.  Cake especially helped me to deploy from a Windows development environment to a device running an Ubuntu operating system – and the principles I’ve learned and written about here don’t just apply to Raspberry Pi devices, I could use them if I wanted to develop a website in .NET Core on my Windows machine, and deploy to a web server running Linux.

Footnote: I’ve written about an improvement to the deployment process to Windows 10 IoT Core here – robocopy makes things much faster

About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!