using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Tango.Scripting { public class ScriptingEngine : IScriptingEngine { private class IncludeResult { public String File { get; set; } public List Lines { get; set; } } public Task Compile(Script script) { return Task.Factory.StartNew(() => { String code = script.Code; List includeResults = new List(); try { includeResults.Add(new IncludeResult() { File = script.File, Lines = script.Code.ToLines() }); code = ReplaceIncludes(script, code, script.WorkingFolder, includeResults); } catch (Exception ex) { throw new CompilationException(new CompilationError() { Message = ex.Message }); } var options = CreateOptions(script); var csharpScript = CSharpScript.Create(code, options: options, globalsType: script.GlobalObject.GetType()); var results = csharpScript.Compile(); List errors = new List(); foreach (var result in results.Where(x => x.Severity == DiagnosticSeverity.Error)) { CompilationError error = new CompilationError(); error.Message = result.GetMessage(); error.Character = result.Location.GetMappedLineSpan().StartLinePosition.Character + 1; int lineIndex = 0; IncludeResult include = null; foreach (var inc in includeResults) { for (int i = 0; i < inc.Lines.Count; i++) { if (inc.Lines[i] == code.ToLines()[result.Location.GetMappedLineSpan().StartLinePosition.Line]) { include = inc; lineIndex = i; break; } } } if (include != null) { error.File = include.File; error.Line = lineIndex + 1; } errors.Add(error); } if (errors.Count > 0) { throw new CompilationException(errors.ToArray()); } return code; }); } public Task Run(Script script) { return Task.Factory.StartNew(() => { var effectivCode = Compile(script).Result; var options = CreateOptions(script); var _cancaller = new CancellationTokenSource(); Thread scriptThread = null; ScriptSession session = null; session = new ScriptSession(script, effectivCode, () => { scriptThread.Abort(); }); scriptThread = new Thread(() => { try { var result = CSharpScript.RunAsync(effectivCode, options: options, globals: script.GlobalObject, cancellationToken: _cancaller.Token).Result; session.Completed(result.ReturnValue); } catch (ThreadAbortException) { } catch (Exception ex) { session.Failed(ex.InnerException); } }); scriptThread.SetApartmentState(script.ApartmentState); scriptThread.IsBackground = true; scriptThread.Start(); return session; }); } public void Dispose() { throw new NotImplementedException(); } #region Private Methods private List GetIncludes(String code, String workingFolder)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.Scripting
{
    public class CompilationError
    {
        public String File { get; set; }

        public String Name
        {
            get { return Path.GetFileName(File); }
        }

        public String Message { get; set; }
        public int Line { get; set; }
        public int Character { get; set; }

        public override string ToString()
        {
            return String.Format("{0}  {1} ({2},{3})", Message, Name, Line, Character);
        }
    }
}