简体   繁体   中英

Execute ScriptCS from c# application

Background

I'm creating ac# 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 ac# 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)

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;
}

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

Question 3 : Personally Id use CS-Script its well maintained, and there is a lot of documentation for it

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM