Scott Smith

Blog Tutorials Projects Speaking RSS

Deeper Dive Into ScriptCS

Welcome to part 2 of the ScriptCS series

  1. Getting started with ScriptCS
  2. Deeper dive into ScriptCS

Introduction

In this article, we will be exploring the newish REPL interactive mode, script packs, and many other cool features of ScriptCS.

ScriptCS allows you to use C# as a scripting language. It harnesses the power of Roslyn and NuGet to enable you to write .NET applications with your favorite editor.

If you are new to ScriptCS, I’d like to suggest reading my previous article Getting started with ScriptCS to learn more about how to install and use it.

REPL

REPL (Read, Eval, Print, Loop) is now supported in the latest release of ScriptCS.

Using REPL with ScriptCS can be done by running ScriptCS without any parameters and allows you to run C# statements from the command prompt without the neeed for files, editors, etc.

1
2
3
4
5
6
7
$ scriptcs
scriptcs (ctrl-c or blank to exit)

> var name = "Scott";
> var location = "California";
> Console.WriteLine(name + " lives in " + location);
Scott lives in California

When you run ScriptCS in REPL mode, you will see some help output on the screen indicating how to end the session. This can be done using Ctrl+C or pressing Enter with no input.

Script Packs

Script packs offer a great way to extend ScriptCS. They provide developers a way to create and share their own extensions for consumption by others using ScriptCS. The current list of available script packs can be found on the ScriptCS Wiki.

Script packs will work in both normal execution and interactive REPL mode.

Adding a script pack to your project can be done in a few ways but the simplest and best option is to use the ScriptCS install directive. You can read about more ways to install packages on the GitHub Wiki.

1
scriptcs -install ScriptCs.WebApi

In this example, we are using ScriptCS to install the package ScriptCs.WebApi into our current directory. This will pull down the assemblies from NuGet, place them in the packages and bin folders, and update packages.config.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
scriptcs -install ScriptCs.WebApi
INFO : Installing packages...
INFO : Installed: ScriptCs.WebApi
INFO : Installation completed successfully.
INFO : Copying assemblies to bin folder...
INFO : Copied: System.Net.Http.Formatting.dll.
INFO : Copied: System.Web.Http.dll.
INFO : Copied: System.Web.Http.SelfHost.dll.
INFO : Copied: System.Net.Http.dll.
INFO : Copied: System.Net.Http.WebRequest.dll.
INFO : Copied: Newtonsoft.Json.dll.
INFO : Copied: ScriptCs.Contracts.dll.
INFO : Copied: ScriptCs.WebApi.Pack.dll.
INFO : Restore completed successfully.
Initiated saving packages into packages.config...
Added Microsoft.AspNet.WebApi.Client, Version 4.0.20710.0, .NET 4.0
Added Microsoft.AspNet.WebApi.Core, Version 4.0.20710.0, .NET 4.0
Added Microsoft.AspNet.WebApi.SelfHost, Version 4.0.20918.0, .NET 4.0
Added Microsoft.Net.Http, Version 2.0.20710.0, .NET 4.5
Added Newtonsoft.Json, Version 4.5.11, .NET 4.0
Added ScriptCs.Contracts, Version 0.3.2, .NET 4.5
Added ScriptCs.WebApi, Version 0.1.0, .NET 4.5
Packages.config successfully created!

Now that the package is installed, we can import it into our script by using Require<T>(). That is the beauty of script packs. They simplify the usage of other functionality that may otherwise be complex.

1
var webApi = Require<WebApi>();

With the inclusion of the WebApi script pack you can actually fire up a working Web API host. Try it out by running the following commands in interactive mode and then browsing to localhost:8888.

1
2
3
4
scriptcs
> var webApi = Require<WebApi>();
> var server = webApi.CreateServer("http://localhost:8888");
> server.OpenAsync().Wait();

To shut the server down make sure to run

1
> server.CloseAsync().Wait();

You may have noticed when you browsed to localhost:8888 the response indicated “No HTTP resource was found that matches the request URI ‘http://localhost:8888/’”. This means we have not yet defined any controllers. To do this we will take advantage of of the #load directive supported by ScriptCS. In your project directory where you installed the ScriptCs.WebApi script pack, create a new script called Controllers.csx with the following code:

1
2
3
4
5
public class ScriptCSController : ApiController {
    public string Get() {
        return "Thanks for using ScriptCS!";
    }
}

This code defines a ScriptCS controller that ScriptCs.WebApi will automatically detect and load when loaded via the Require<T>() command.

In order to use this newly created script we will need to reference it using the #load directive. The #load directive is used to reference other scripts from within your script or interactive session. It must be placed at the top of a script otherwise it will be ignored. Also, you can use both relative and absolute paths.

1
2
3
4
5
scriptcs
> #load "Controllers.csx";
> var webApi = Require<WebApi>();
> var server = webApi.CreateServer("http://localhost:8888");
> server.OpenAsync().Wait();

Now when you browse to localhost:8888/ScriptCS you will see the response message “Thanks for using ScriptCS!”. Finally, don’t forget to shut the server down like we did before.

Another directive worth mentioning is #r. This directive is used to explicitly reference assemblies within the GAC or your local bin folder. If you have added assemblies via the scriptcs -install or scriptcs -restore commands you do not need to use the #r directive. It is used for including other assemblies.

1
#r "MyCustomAssembly.dll"

Building a Script Pack

Rather than reinvent the wheel, I will refer to a great blog post by Martin Doms on Building a scriptcs script pack.

ClrMD

ClrMD, Microsoft.Diagnostics.Runtime component, is a set of advanced APIs for programmatically inspecting a crash dump of a .NET program and performing live process inspection. It allows you to write automated crash analysis for your applications and automate many common debugger tasks.

This is a fabulous fit for the scriptable nature of ScriptCS. Using ScriptCS and ClrMD we have an environment where we can interactively debug and inspect .NET programs and processes.

There are currently two projects in very early stages attempting to create script packs for ClrMD.

ScriptCs.ClrDiagnostics
ScriptCs.ClrMD

I would highly suggest taking a look at both.

Summary

ScriptCS is already a very powerful, flexible, and user friendly environment for working with C# as a scripting language. It takes advantage of an elegant language, incorporates Roslyn, and utilizes NuGet to provide scriptable C#, REPL, and Script Packs. I am personally looking forward to what will be coming next.

Thanks for reading.