7

Background

I'm creating a c# application that runs some status checks (think nagios style checks).

What I ideally want is this c# application to look at a specific directory, and just compile/execute any scriptcs scripts within it, and act on the results (send email alerts for failing status checks for example).

I would expect the script to return an integer or something (for example) and that integer would indicate weather the status check succeeded or failed.

Values returned back to C# application.

0 - Success
1 - Warning
2 - Error

When first tasked with this I thought this is a job for MEF, but it would be vastly more convenient to create these 'status checks' without having to create a project or compile anything, just plopping a scriptcs script within a folder seems way more attractive.

So my questions are

  1. Is there any documentation/samples on using a c# app and scriptcs together (google didn't net me much)?

  2. Is this a use case for scriptcs or was it never really intended to be used like this?

  3. Would I have an easier time just creating a custom solution using roslyn or some dynamic compilation/execution? (I have very little experience with scriptsc)

Kyle Gobel
  • 5,530
  • 9
  • 45
  • 68

4 Answers4

6

I found some good easy examples on how to do this:

Loading a script from a file on disk and running it: https://github.com/glennblock/scriptcs-hosting-example

A web site where you can submit code, and it will return the result: https://github.com/filipw/sample-scriptcs-webhost

Here is an example of how to load a script file, run it and return the result:

public dynamic RunScript()
{
    var logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    var scriptServicesBuilder = new ScriptServicesBuilder(new ScriptConsole(), logger).
        LogLevel(LogLevel.Info).Cache(false).Repl(false).ScriptEngine<RoslynScriptEngine>();

    var scriptcs = scriptServicesBuilder.Build();

    scriptcs.Executor.Initialize(new[] { "System.Web" }, Enumerable.Empty<IScriptPack>());
    scriptcs.Executor.AddReferences(Assembly.GetExecutingAssembly());

    var result = scriptcs.Executor.Execute("HelloWorld.csx");

    scriptcs.Executor.Terminate();

    if (result.CompileExceptionInfo != null)
        return new { error = result.CompileExceptionInfo.SourceException.Message };
    if (result.ExecuteExceptionInfo != null)
        return new { error = result.ExecuteExceptionInfo.SourceException.Message };

    return result.ReturnValue;
}
jmc
  • 1,058
  • 1
  • 12
  • 20
2

Question 2: A scripting language could work well in this situation as long you understand a bit about them.

Question 3: Personally I'd use CS-Script - it's well maintained, and there is a lot of documentation for it.

halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
1

Sorry if I go a little bit off topic but the question ignited my imagination, and I thought...

IMMO scriptcs is more of scripting environment it self , a bit like NodeCs kind of thing... It doesn't need anything to give a scripting environment out of the box. But as far I could see . does not provide an managed api to a .net application. Of course I could be wrong, and it would be a matter of looking at the source, because from the docs I also couldn't find a reference;

It seems to me You'll be better of integrating Roslyn api your self.

EDIT: I was wrong, ScriptCs scriptcs.hosting Nuget packages is the entry point, and I can see here how Glimpse, and MakeSharp did it;

But there is EdgeJs, out of the box gives you pretty much what you want, but the scripts will be Javascripts on NodeJs, but it seems is not what you want.

What if you try to load c# scripts straight from Edge, it can compile python,F#,c#, csx's ... But its also doing it from Node env, not .net (or did I miss something?)

Anyway...it occurred to me you could load Edge from .Net load Edge again from Node and Call a .Net script which will in turns return something to .Net again.

It feels like an overkill , but so nicely isolated that it might be worth a try. and besides some setup there isn't much to code for it.

I loaded the experiment on GitHub.

Dan
  • 2,818
  • 23
  • 21
1

Question 1. I made an (ugly) example integration test executing ScriptCS from C# with System.Diagnostics.Process.Start() (Involves Powershell in this case) I't should answer your first question i hope.

    [Test, Explicit]
    public void RunScriptCsFile_FilePrintsTheValue2_StreamIsParsedCorrectly() {
        var scriptFile = @"C:\Projects\test-project\test-project.Tests\test-file.csx";
        var param = string.Format("scriptcs {0}", scriptFile);
        Process executeScript = new Process {
            StartInfo = new ProcessStartInfo {
                FileName = "powershell.exe",
                Arguments = param,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                CreateNoWindow = true
            }
        };

        executeScript.Start();
        var value = -1;
        while (!executeScript.StandardOutput.EndOfStream) {
            string line = executeScript.StandardOutput.ReadLine();
            if (int.TryParse(line, out value)) {
                Assert.AreEqual(2, value);
            }
        }
    }

The test-file.csx only contains Console.WriteLine("2"); As an "error" example for your case.

Question 3. I've done a similar thing with Shovel ScriptPack for ScriptCS, It might be worth to check out.

Dennie
  • 163
  • 1
  • 9