C# scripts using dotnet-script
Tags: dotnet, csharp
Published: 2019-04-05 23:28:37

---
title: C# scripts using dotnet-script
published: true
tags: dotnet,csharp
canonical_url: https://gldraphael.com/blog/csharp-scripts-using-dotnet-script/
---

You know how the python folks can just write some code in a `.py` file and run it with `python3 filename.py`, without going through the "new project" and the "`public static void main`" ceremony that C# users have to? C# can write scripts too – something I learnt just like a year back.

Roslyn made C# scripts possible. There's a Jan 2016 MSDN blogpost by [Mark Michaelis](https://twitter.com/@markmichaelis) titled [C# Scripting](https://msdn.microsoft.com/en-us/magazine/mt614271.aspx) if you're interested.

The tool that I've been really fascinated by is [dotnet-script](https://github.com/filipw/dotnet-script), which is a cross-platform .NET Core global tool with full intellisense support on VS Code via omnisharp and covers most use-cases for your experimenting needs.

## Prerequisites

1. .NET Core SDK 2.1+
2. VS Code
3. Official C# Extension for VS Code

## Installation 

First make sure you have the latest version of .NET Core SDK installed from [dot.net](https://dot.net). The minimum requirement is .NET Core 2.1.

The easiest way to install `dotnet-script` is installing it as a global tool:

```bash
dotnet tool install --global dotnet-script

```

You should now be able to run `dotnet script --version` and it should print the version of the `dotnet-script` tool.

## Hello world

1. Create a new directory to store all your scripts.
2. Init a new script.
3. Run.

```bash
mkdir console
cd console
dotnet script init hello
dotnet script hello.csx

```

- The init command creates a `.csx` (C# script) file along with an `omnisharp.json` file for intellisense and a VS Code `launch.json` file for debug support. 
- The csx script is run using `dotnet script filename`.

![](https://gldraphael.com/content/images/2019/04/dotnet-script-screenshot.png)

The generated `hello.csx` file has the following contents:

```csharp
#!/usr/bin/env dotnet-script

Console.WriteLine("Hello world!");

```

The first line is a shebang that \*nix users must be familiar with. It means we can run it as `./hello.csx` and it'll just work! (Also works on windows, but you'll need to associate `.csx` files with dotnet-script first using `dotnet script register`.)

## Another quick example

A typical use-case for console applications is to experiment with new libraries, and `dotnet-script` is the perfect tool for the job. Let's say I'm learning about the [stateless](https://github.com/dotnet-state-machine/stateless) library. Here's how I'd go about experimenting:

1. Create a new script using `dotnet script init stateless`.
2. Open the folder in VS Code using `code .`.
3. Import the nuget package using the roslyn `#r` directive.
4. Go to their GitHub page and copy some sample code over.
5. Add using statements if needed using `Cmd+.` (or `Ctrl+.`).
6. Debug within VS code with F5.

Here's my `stateless.csx` file:

```csharp
#!/usr/bin/env dotnet-script
#r "nuget: Stateless, 4.2.1"

// Copied from: https://github.com/dotnet-state-machine/stateless/blob/dev/example/OnOffExample/Program.cs
using Stateless;

const string on = "On";
const string off = "Off";
const char space = ' ';

// Instantiate a new state machine in the 'off' state
var onOffSwitch = new StateMachine<string, char>(off);

// Configure state machine with the Configure method, supplying the state to be configured as a parameter
onOffSwitch.Configure(off).Permit(space, on);
onOffSwitch.Configure(on).Permit(space, off);

Console.WriteLine("Press <space> to toggle the switch. Any other key will exit the program.");

while (true)
{
    Console.WriteLine("Switch is in state: " + onOffSwitch.State);
    var pressed = Console.ReadKey(true).KeyChar;
    
    // Check if user wants to exit
    if (pressed != space) break;

    // Use the Fire method with the trigger as payload to supply the state machine with an event.
    // The state machine will react according to its configuration.
    onOffSwitch.Fire(pressed);
}

```

Notes for those new to developing using VS Code:

- If intellisense doesn't work after 3, or no code-actions are available after 5, you might need to restart omnisharp by: `Cmd+Shift+P` --> `Omnisharp: Restart Omnisharp`. See [filipw/dotnet-script#424](https://github.com/filipw/dotnet-script/issues/424) for more information.
- While running the application you'll most likely see this error: "Cannot read keys when either application does not have a console or when console input has been redirected." because VS Code uses the Debug Console by default which doesn't support console input. You can change that by configuring it to use the integrated terminal instead, by adding a `"console": "integratedTerminal"` property to `.vscode/launch.json`. More information [here](https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window).

That's it. If you ask me I think it's pretty slick.

* * *

What I love about `dotnet-script` is:

1. All _relevant_ code, including required nuget packages, can exist in a single file.
2. Full and reliable intellisense.
3. Debugger support.
4. No `public static void main` or `.csproj` files.