Learn Roslyn Now: Part 14 Intro to the Scripting API

The Scripting API is finally here! After being removed from Roslyn’s 1.0 release it’s now available (for C#) in pre-release format on NuGet. To install to your project just run:

Install-Package Microsoft.CodeAnalysis.Scripting -Pre

Note: You need to target .NET 4.6 or you’ll get the following exception when running your scripts:

Could not load file or assembly 'System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

Note: Today (October 15, 2015) the Scripting APIs depend on the 1.1.0-beta1 release, so you’ll have to update your Microsoft.CodeAnalysis references to match if you want to use all of Roslyn with the scripting stuff.

There are a few different ways to use the Scripting API.

EvaluateAsync

CSharpScript.EvaluateAsync is probably the simplest way to get started evaluating expressions. Simple pass any expression that would return a single result to this method it will be evaluated for you.

RunAsync

Not every script returns a single value. For more complex scripts we may want to keep track of state or inspect different variables. CSharpScript.RunAsync creates and returns a ScriptState object that allows us to do exactly this. Take a look:

We can also maintain the state of our script and continue applying changes to it with ScriptState.ContinueWith():

ScriptOptions

We can start to get into more interesting code by adding references to DLLs that we’d like to use. We use ScriptOptions to provide out script with the proper MetadataReferences.

This stuff is surprisingly broad. The Microsoft.CodeAnalysis.Scripting namespace is full of public types that I’m not at all familiar with and there’s a lot left to learn. I’m excited to see what people will build with this and how they might be able to incorporate scripting into their applications.

Kasey Uhlenhuth from the Roslyn team has compiled a list of code snippets to help get you off the ground with the Scripting API. Check them out on GitHub!

If you’ve got some cool plans for the scripting API, let me know if the comments below!

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

12 Responses to Learn Roslyn Now: Part 14 Intro to the Scripting API

  1. oceanswave says:

    Previously (as in 2011) one of the major features of Roslyn-based scripting was that the script executes in a sandbox. Is this still true?

  2. Frank Bakker says:

    Hey Josh, your Blog really helped me understand Roslyn, many google searches ended me up here!

    The coolest usage of scripting I could come up with is scripting against the Roslyn API itself from within Visual Studio.
    Check it out at http://blog.frankbakker.net/2015/11/find-code-patterns-using-c-and-roslyn.html

  3. canerozden13 says:

    Hey Josh, how we can we reach to you via e-mail ?

  4. Bob says:

    I keep getting the Error Severity Code Description Project File Line Suppression State
    Error CS1061 ‘ScriptOptions’ does not contain a definition for ‘AddNamespace’ and no extension method ‘AddNamespace’ accepting a first argument of type ‘ScriptOptions’ could be found (are you missing a using directive or an assembly reference?) testcXML C:\Users\bbabb\Documents\Visual Studio 2013\Projects\KMBScXML\testcXML\Program.cs 56 Active

  5. This is pretty cool. If you wanted to expose this to the internet, how would you secure the API surface area? I have raised a GitHub issue discussing this here https://github.com/dotnet/roslyn/issues/10830.

  6. 李瑞康 says:

    Hey Josh, I raised a question on the StackOverflow
    (http://stackoverflow.com/questions/41464734/how-to-pause-or-stop-csharpscript-running/41471198#41471198) as following

    I’m using Roslyn’s scripting API in my application, code snippet as following:

    public class ScriptEngine
    {
    public static string CodeText;
    public static event Action CompileErrorEvent;

    public static async Task RunScriptAsync(CancellationToken ct)
    {
    try
    {
    var scriptResult = await CSharpScript.RunAsync(CodeText, null, new ScriptHost(), null, ct);
    return true;
    }
    catch (Microsoft.CodeAnalysis.Scripting.CompilationErrorException ex)
    {
    List result = new List();

    foreach (var item in ex.Diagnostics)
    {
    result.Add(item.ToString());
    }

    if (result.Count > 0)
    {
    CompileErrorEvent?.Invoke(result.ToArray());
    }

    return false;
    }
    catch (Exception ex)
    {
    IMCP_Base.Dialog.Show.SimpleError(“脚本运行”, ex.Message, “修改脚本”);
    return false;
    }
    }
    …….
    }

    public static CancellationTokenSource ScriptCTS;

    private async void btnScriptRun_ItemClick(object sender, ItemClickEventArgs e)
    {
    ScriptCTS = new CancellationTokenSource();

    if (CheckScriptEditorIsNotNull())
    {
    Script.ScriptEngine.CodeText = ScriptEditor.GetCode();
    bool runSuccess = await Script.ScriptEngine.RunScriptAsync(ScriptCTS.Token);
    }
    }

    private void btnScriptStop_ItemClick(object sender, ItemClickEventArgs e)
    {
    ScriptCTS?.Cancel();
    }
    CSharpScript.RunAsync method runs well, but when I click ScriptStop button, ScriptCTS?.Cancel() can’t cancel running script.

    How can I stop or pause a script running?

  7. Brandon says:

    I had to make some edits to the second code sample to get it to work.

    1. The `RunAsync` argument needed two more double-quotes added at the end (otherwise it resulted in CS1010).
    2. The calls to `state.Variables[…];` had to be changed to `state.Result.Variables.Single(v => v.Name == …);`

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s