public async Task MissingRefrencesAutoResolution() { var portableLib = CSharpCompilation.Create( "PortableLib", new[] { SyntaxFactory.ParseSyntaxTree("public class C {}") }, new[] { SystemRuntimePP7Ref }, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); var portableLibRef = portableLib.ToMetadataReference(); var loader = new InteractiveAssemblyLoader(); loader.RegisterDependency(Assembly.Load(portableLib.EmitToArray().ToArray())); var s0 = await CSharpScript.Create("new C()", options : ScriptOptions.Default.AddReferences(portableLibRef), assemblyLoader : loader).RunAsync(); var c0 = s0.Script.GetCompilation(); // includes corlib, host type assembly by default: AssertEx.Equal(new[] { typeof(object).GetTypeInfo().Assembly.Location, "PortableLib" }, c0.ExternalReferences.SelectAsArray(m => m.Display)); // System.Runtime, 4.0.0.0 depends on all the assemblies below: AssertEx.Equal(new[] { "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "PortableLib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Data.SqlXml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", }, c0.GetBoundReferenceManager().GetReferencedAssemblies().Select(a => a.Value.Identity.GetDisplayName())); }
public void Initialize(Type replServiceProviderType, string cultureName) { Debug.Assert(replServiceProviderType != null); Debug.Assert(cultureName != null); Debug.Assert(_metadataFileProvider == null); Debug.Assert(_assemblyLoader == null); Debug.Assert(_replServiceProvider == null); // TODO (tomat): we should share the copied files with the host _metadataFileProvider = new MetadataShadowCopyProvider( Path.Combine(Path.GetTempPath(), "InteractiveHostShadow"), noShadowCopyDirectories: s_systemNoShadowCopyDirectories, documentationCommentsCulture: new CultureInfo(cultureName)); _assemblyLoader = new InteractiveAssemblyLoader(_metadataFileProvider); _replServiceProvider = (ReplServiceProvider)Activator.CreateInstance(replServiceProviderType); _globals = new InteractiveScriptGlobals(Console.Out, _replServiceProvider.ObjectFormatter); }
private async void CommandBox_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter && !Keyboard.Modifiers.HasFlag(ModifierKeys.Shift)) { Debug.WriteLine(CommandBox.Text); e.Handled = true; CommandBox.IsEnabled = false; object result; try { using (var loader = new InteractiveAssemblyLoader()) { loader.RegisterDependency(typeof(UndertaleObject).GetTypeInfo().Assembly); var script = CSharpScript.Create <object>(CommandBox.Text, ScriptOptions.Default .AddImports("UndertaleModLib", "UndertaleModLib.Models", "UndertaleModLib.Decompiler", "UndertaleModLib.Scripting") .AddImports("System", "System.IO", "System.Collections.Generic", "System.Text.RegularExpressions") .AddReferences(Program.GetAssemblyMetadata(typeof(UndertaleObject).GetTypeInfo().Assembly)) .AddReferences(typeof(System.Text.RegularExpressions.Regex).GetTypeInfo().Assembly), typeof(IScriptInterface), loader); result = (await script.RunAsync(this)).ReturnValue; } } catch (CompilationErrorException exc) { result = exc.Message; Debug.WriteLine(exc); } catch (Exception exc) { result = exc; } CommandBox.Text = result != null?result.ToString() : ""; CommandBox.IsEnabled = true; } }
public virtual ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } Logger.Verbose($"Current runtime is '{_scriptEnvironment.PlatformIdentifier}'."); RuntimeDependency[] runtimeDependencies = GetRuntimeDependencies(context); var encoding = context.Code.Encoding ?? Encoding.UTF8; // encoding is required when emitting debug information var scriptOptions = CreateScriptOptions(context, runtimeDependencies.ToList()) .WithFileEncoding(encoding); var loadedAssembliesMap = CreateLoadedAssembliesMap(); var scriptDependenciesMap = CreateScriptDependenciesMap(runtimeDependencies); scriptOptions = AddScriptReferences(scriptOptions, loadedAssembliesMap, scriptDependenciesMap); LoadNativeAssets(runtimeDependencies); AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => MapUnresolvedAssemblyToRuntimeLibrary(scriptDependenciesMap, loadedAssembliesMap, args); string code = GetScriptCode(context); var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(code, scriptOptions, typeof(THost), loader); SetOptimizationLevel(context, script); EvaluateDiagnostics(script); return(new ScriptCompilationContext <TReturn>(script, context.Code, loader, scriptOptions)); }
public virtual ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } Logger.Verbose($"Current runtime is '{RuntimeHelper.GetPlatformIdentifier()}'."); var runtimeDependencies = RuntimeDependencyResolver.GetDependencies(context.WorkingDirectory, context.ScriptMode, context.Code.ToString()).ToArray(); var scriptOptions = CreateScriptOptions(context, runtimeDependencies.ToList()); var loadedAssembliesMap = CreateLoadedAssembliesMap(); var scriptDependenciesMap = CreateScriptDependenciesMap(runtimeDependencies); scriptOptions = AddScriptReferences(scriptOptions, loadedAssembliesMap, scriptDependenciesMap); LoadNativeAssets(runtimeDependencies); AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => MapUnresolvedAssemblyToRuntimeLibrary(scriptDependenciesMap, loadedAssembliesMap, args); string code = GetScriptCode(context); var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(code, scriptOptions, typeof(THost), loader); SetOptimizationLevel(context, script); EvaluateDiagnostics(script); return(new ScriptCompilationContext <TReturn>(script, context.Code, loader, scriptOptions)); }
// SCRIPT evaluate python script in node name or in node note in node private async System.Threading.Tasks.Task EvaluateAsync(Diagram.Diagram diagram, DiagramView diagramView, Node node, string clipboard = "") { string body = node.note; if (this.interactiveLoader == null) { this.interactiveLoader = new InteractiveAssemblyLoader(); } if (this.scriptOptions == null) { this.scriptOptions = ScriptOptions.Default; var asms = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly asm in asms) { Program.log.Write("CSScriptPlugin: " + asm.ManifestModule.Name); if (asm.ManifestModule.Name == "InfiniteDiagram.exe") { this.scriptOptions = this.scriptOptions.AddReferences(asm); } } this.scriptOptions = this.scriptOptions.AddImports("Diagram"); } System.Threading.Tasks.Task <ScriptState <object> > task = CSharpScript.Create( options: this.scriptOptions, code: body, globalsType: typeof(Globals), assemblyLoader: this.interactiveLoader ) .RunAsync(new Globals { Script = new Tools(diagram, diagramView, node, clipboard) });; }
public void HostObjectInInMemoryAssembly() { var lib = CreateCSharpCompilation("public class C { public int X = 1, Y = 2; }", new[] { TestReferences.NetFx.v4_0_30319.mscorlib }, "HostLib"); var libImage = lib.EmitToArray(); var libRef = MetadataImageReference.CreateFromImage(libImage); var libAssembly = Assembly.Load(libImage.ToArray()); var globalsType = libAssembly.GetType("C"); var globals = Activator.CreateInstance(globalsType); using (var loader = new InteractiveAssemblyLoader()) { loader.RegisterDependency(libAssembly); var script = CSharpScript.Create <int>( "X+Y", ScriptOptions.Default.WithReferences(libRef), globalsType: globalsType, assemblyLoader: loader); int result = script.RunAsync(globals).Result.ReturnValue; Assert.Equal(3, result); } }
public Service() { // TODO (tomat): we should share the copied files with the host _metadataFileProvider = new MetadataShadowCopyProvider( Path.Combine(Path.GetTempPath(), "InteractiveHostShadow"), noShadowCopyDirectories: s_systemNoShadowCopyDirectories); _options = ScriptOptions.Default.WithSearchPaths(DefaultReferenceSearchPaths); _assemblyLoader = new InteractiveAssemblyLoader(_metadataFileProvider); _sourceSearchPaths = DefaultSourceSearchPaths; _formattingOptions = new ObjectFormattingOptions( memberFormat: MemberDisplayFormat.Inline, quoteStrings: true, useHexadecimalNumbers: false, maxOutputLength: 200, memberIndentation: " "); // We want to be sure to delete the shadow-copied files when the process goes away. Frankly // there's nothing we can do if the process is forcefully quit or goes down in a completely // uncontrolled manner (like a stack overflow). When the process goes down in a controlled // manned, we should generally expect this event to be called. AppDomain.CurrentDomain.ProcessExit += HandleProcessExit; }
public ScriptCompilationContext(Script <TReturn> script, SourceText sourceText, InteractiveAssemblyLoader loader, ScriptOptions scriptOptions, RuntimeDependency[] runtimeDependencies, Diagnostic[] diagnostics) { Script = script; SourceText = sourceText; ScriptOptions = scriptOptions; Loader = loader; RuntimeDependencies = runtimeDependencies; Warnings = diagnostics.Where(x => x.Severity == DiagnosticSeverity.Warning).ToArray(); Errors = diagnostics.Where(x => x.Severity == DiagnosticSeverity.Error).ToArray(); }
public ScriptCompilationContext(Script <TReturn> script, SourceText sourceText, InteractiveAssemblyLoader loader, ScriptOptions scriptOptions, RuntimeDependency[] runtimeDependencies) { Script = script; SourceText = sourceText; ScriptOptions = scriptOptions; Loader = loader; RuntimeDependencies = runtimeDependencies; }
public virtual ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var runtimeContext = ProjectContext.CreateContextForEachTarget(context.WorkingDirectory).First(); var runtimeIdentitfer = GetRuntimeIdentitifer(); _logger.Verbose($"Current runtime is '{runtimeIdentitfer}'."); _logger.Verbose($"Found runtime context for '{runtimeContext.ProjectFile.ProjectFilePath}'."); var projectExporter = runtimeContext.CreateExporter(context.Configuration); var runtimeDependencies = new HashSet <string>(); var projectDependencies = projectExporter.GetDependencies(); foreach (var projectDependency in projectDependencies) { var runtimeAssemblyGroups = projectDependency.RuntimeAssemblyGroups; foreach (var libraryAsset in runtimeAssemblyGroups.GetDefaultAssets()) { var runtimeAssemblyPath = libraryAsset.ResolvedPath; _logger.Verbose($"Discovered runtime dependency for '{runtimeAssemblyPath}'"); runtimeDependencies.Add(runtimeAssemblyPath); } foreach (var runtimeAssemblyGroup in runtimeAssemblyGroups) { if (!string.IsNullOrWhiteSpace(runtimeAssemblyGroup.Runtime) && runtimeAssemblyGroup.Runtime == runtimeIdentitfer) { foreach (var runtimeAsset in runtimeAssemblyGroups.GetRuntimeAssets(GetRuntimeIdentitifer())) { var runtimeAssetPath = runtimeAsset.ResolvedPath; _logger.Verbose($"Discovered runtime asset dependency ('{runtimeIdentitfer}') for '{runtimeAssetPath}'"); runtimeDependencies.Add(runtimeAssetPath); } } } } var opts = CreateScriptOptions(context); var runtimeId = RuntimeEnvironment.GetRuntimeIdentifier(); var inheritedAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(runtimeId).Where(x => x.FullName.StartsWith("system.", StringComparison.OrdinalIgnoreCase) || x.FullName.StartsWith("microsoft.codeanalysis", StringComparison.OrdinalIgnoreCase) || x.FullName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase)); foreach (var inheritedAssemblyName in inheritedAssemblyNames) { _logger.Verbose("Adding reference to an inherited dependency => " + inheritedAssemblyName.FullName); var assembly = Assembly.Load(inheritedAssemblyName); opts = opts.AddReferences(assembly); } foreach (var runtimeDep in runtimeDependencies) { _logger.Verbose("Adding reference to a runtime dependency => " + runtimeDep); opts = opts.AddReferences(MetadataReference.CreateFromFile(runtimeDep)); } var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(context.Code.ToString(), opts, typeof(THost), loader); var compilation = script.GetCompilation(); var diagnostics = compilation.GetDiagnostics(); var orderedDiagnostics = diagnostics.OrderBy((d1, d2) => { var severityDiff = (int)d2.Severity - (int)d1.Severity; return(severityDiff != 0 ? severityDiff : d1.Location.SourceSpan.Start - d2.Location.SourceSpan.Start); }); if (orderedDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { foreach (var diagnostic in orderedDiagnostics) { _logger.Log(diagnostic.ToString()); } throw new CompilationErrorException("Script compilation failed due to one or more errors.", orderedDiagnostics.ToImmutableArray()); } return(new ScriptCompilationContext <TReturn>(script, context.Code, loader)); }
protected override Script <T> Create <T>(string code, ScriptOptions options, Type globalsType, InteractiveAssemblyLoader assemblyLoader) => CSharpScript.Create <T>(code, options, globalsType, assemblyLoader);
public ScriptCompilationContext(Script <TReturn> script, SourceText sourceText, InteractiveAssemblyLoader loader) { Script = script; SourceText = sourceText; Loader = loader; }
/// <summary> /// Create a new C# script. /// </summary> /// <param name="code">The source code of the script.</param> /// <param name="options">The script options.</param> /// <param name="globalsType">Type of global object.</param> /// <param name="assemblyLoader">Custom assembly loader.</param> public static Script <object> Create(string code, ScriptOptions options = null, Type globalsType = null, InteractiveAssemblyLoader assemblyLoader = null) { return(Create <object>(code, options, globalsType, assemblyLoader)); }
/// <summary> /// Create a new C# script. /// </summary> /// <param name="code">The <see cref="Stream"/> representing the source code of the script.</param> /// <param name="options">The script options.</param> /// <param name="globalsType">Type of global object.</param> /// <param name="assemblyLoader">Custom assembly loader.</param> /// <exception cref="ArgumentNullException">Stream is null.</exception> /// <exception cref="ArgumentException">Stream is not readable or seekable.</exception> public static Script <object> Create(Stream code, ScriptOptions options = null, Type globalsType = null, InteractiveAssemblyLoader assemblyLoader = null) { if (code == null) { throw new ArgumentNullException(nameof(code)); } return(Create <object>(code, options, globalsType, assemblyLoader)); }
public async Task <EvaluationDetails?> EvaluateAsync(RiasCommandContext context, string code) { var globals = new RoslynGlobals { Rias = RiasBot, Context = context }; var imports = new[] { "System", "System.Collections.Generic", "System.Linq", "Disqord", "Disqord.WebSocket", "System.Threading.Tasks", "System.Text", "Microsoft.Extensions.DependencyInjection", "System.Net.Http", "Rias.Core.Extensions", "Rias.Core.Database", "Qmmands" }; var scriptOptions = ScriptOptions.Default.WithReferences(typeof(Rias).Assembly).AddImports(imports); code = SanitizeCode(code); using var loader = new InteractiveAssemblyLoader(); var sw = Stopwatch.StartNew(); var script = CSharpScript.Create(code, scriptOptions, typeof(RoslynGlobals), loader); var diagnostics = script.Compile(); sw.Stop(); var compilationTime = sw.Elapsed; if (diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) { return(new EvaluationDetails { CompilationTime = compilationTime, Code = code, IsCompiled = false, Exception = string.Join("\n", diagnostics.Select(x => x.ToString())) }); } sw.Restart(); try { var result = await script.RunAsync(globals); sw.Stop(); if (result.ReturnValue is null) { return(null); } var evaluationDetails = new EvaluationDetails { CompilationTime = compilationTime, ExecutionTime = sw.Elapsed, Code = code, IsCompiled = true, Success = true }; var returnValue = result.ReturnValue; var type = result.ReturnValue.GetType(); switch (returnValue) { case string str: evaluationDetails.Result = str; evaluationDetails.ReturnType = type.Name; break; case IEnumerable enumerable: var list = enumerable.Cast <object>().ToList(); var enumType = enumerable.GetType(); evaluationDetails.Result = list.Count != 0 ? $"[{string.Join(", ", list)}]" : "empty"; evaluationDetails.ReturnType = $"{enumType.Name}<{string.Join(", ", enumType.GenericTypeArguments.Select(t => t.Name))}>"; break; case Enum @enum: evaluationDetails.Result = @enum.ToString(); evaluationDetails.ReturnType = @enum.GetType().Name; break; default: evaluationDetails.Result = returnValue.ToString(); evaluationDetails.ReturnType = type.Name; break; } return(evaluationDetails); } catch (Exception ex) { sw.Stop(); return(new EvaluationDetails { CompilationTime = compilationTime, ExecutionTime = sw.Elapsed, Code = code, ReturnType = ex.GetType().Name, IsCompiled = true, Success = false, Exception = ex.Message }); } }
public Loader(Uri scriptUri, ScriptOptions options, InteractiveAssemblyLoader assemblyLoader) { this.scriptUri = scriptUri; this.options = options; this.assemblyLoader = assemblyLoader; }
/// <summary> /// Create a new C# script. /// </summary> /// <param name="code">The <see cref="Stream"/> representing the source code of the script.</param> /// <param name="options">The script options.</param> /// <param name="globalsType">Type of global object.</param> /// <param name="assemblyLoader">Custom assembly loader.</param> /// <typeparam name="T">The return type of the script</typeparam> /// <exception cref="ArgumentNullException">Stream is null.</exception> /// <exception cref="ArgumentException">Stream is not readable or seekable.</exception> public static Script <T> Create <T>(Stream code, ScriptOptions options = null, Type globalsType = null, InteractiveAssemblyLoader assemblyLoader = null) { if (code == null) { throw new ArgumentNullException(nameof(code)); } return(Script.CreateInitialScript <T>(CSharpScriptCompiler.Instance, SourceText.From(code, options?.FileEncoding), options, globalsType, assemblyLoader)); }
public ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var runtimeContext = ProjectContext.CreateContextForEachTarget(context.WorkingDirectory).First(); _logger.Verbose($"Found runtime context for '{runtimeContext.ProjectFile.ProjectFilePath}'"); var projectExporter = runtimeContext.CreateExporter(context.Configuration); var runtimeDependencies = new HashSet <string>(); var projectDependencies = projectExporter.GetDependencies(); foreach (var projectDependency in projectDependencies) { var runtimeAssemblies = projectDependency.RuntimeAssemblyGroups; foreach (var runtimeAssembly in runtimeAssemblies.GetDefaultAssets()) { var runtimeAssemblyPath = runtimeAssembly.ResolvedPath; _logger.Verbose($"Discovered runtime dependency for '{runtimeAssemblyPath}'"); runtimeDependencies.Add(runtimeAssemblyPath); } } var opts = ScriptOptions.Default. AddImports(DefaultNamespaces). AddReferences(DefaultAssemblies). WithSourceResolver(new RemoteFileResolver(context.WorkingDirectory)); if (!string.IsNullOrWhiteSpace(context.FilePath)) { opts = opts.WithFilePath(context.FilePath); } var runtimeId = RuntimeEnvironment.GetRuntimeIdentifier(); var inheritedAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(runtimeId).Where(x => x.FullName.ToLowerInvariant().StartsWith("system.") || x.FullName.ToLowerInvariant().StartsWith("microsoft.codeanalysis") || x.FullName.ToLowerInvariant().StartsWith("mscorlib")); foreach (var inheritedAssemblyName in inheritedAssemblyNames) { _logger.Verbose("Adding reference to an inherited dependency => " + inheritedAssemblyName.FullName); var assembly = Assembly.Load(inheritedAssemblyName); opts = opts.AddReferences(assembly); } foreach (var runtimeDep in runtimeDependencies) { _logger.Verbose("Adding reference to a runtime dependency => " + runtimeDep); opts = opts.AddReferences(MetadataReference.CreateFromFile(runtimeDep)); } var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(context.Code.ToString(), opts, typeof(THost), loader); var compilation = script.GetCompilation(); var diagnostics = compilation.GetDiagnostics(); if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { foreach (var diagnostic in diagnostics) { _logger.Log(diagnostic.ToString()); } throw new CompilationErrorException("Script compilation failed due to one or more errors.", diagnostics); } return(new ScriptCompilationContext <TReturn>(script, context.Code, loader)); }
private static async Task RunScript() { var code = @" // Demo 1: Resolve reference with custom source reference resolver. #load ""WelcomeScript.csx"" // Demo 2: Resolve reference with custom metadata reference resolver. #r ""MathNet.Numerics.dll"" using System; using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Double; Matrix<double> A = DenseMatrix.OfArray(new double[,] { {1,1,1,1}, {1,2,3,4}, {4,3,2,1}}); Vector<double>[] nullspace = A.Kernel(); // verify: the following should be approximately (0,0,0) var result = (A * (2*nullspace[0] - 3*nullspace[1])); Console.WriteLine(); Console.WriteLine(""Demo 1""); Console.WriteLine(); Console.WriteLine(""If you can see the Welcome box above, demo 1 was successful.""); Console.WriteLine(); Console.WriteLine(""#########################################################################################""); Console.WriteLine(); Console.WriteLine(""Demo 2""); Console.WriteLine(); Console.WriteLine(""The null space was calculated by the script. This is the result:""); Console.WriteLine(); Console.WriteLine(result.ToString()); Console.WriteLine(""So we have the evidence that demo 2 works as well, because MathNet.Numerics.dll could be resolved.""); Console.WriteLine(); "; var loader = new InteractiveAssemblyLoader(); var options = ScriptOptions .Default .WithMetadataResolver(new CustomMetadataReferenceResolver()) .WithSourceResolver(new CustomSourceReferenceResolver()) .WithFilePath(Environment.CurrentDirectory); var script = CSharpScript.Create(code, options, null, loader); var scriptState = await script.RunAsync(); Console.WriteLine("#########################################################################################"); Console.WriteLine($"{Environment.NewLine}Demo 3"); Console.WriteLine($"{Environment.NewLine}Use InteractiveAssemblyLoader to made dynamic generates types available in the script."); Console.WriteLine($"{Environment.NewLine}First, let's try to create an instance of 'DynamicGeneratedClass1' by continuing the current script...{Environment.NewLine}"); script = script.ContinueWith("var instance = new DynamicGeneratedClass1();"); Console.WriteLine($"An error occured: {script.Compile().First().GetMessage()}"); Console.WriteLine($"{Environment.NewLine}Now we generate the types DynamicGeneratedBaseClass, DynamicGeneratedClass1 and DynamicGeneratedClass2 in a in-memory assembly and expose the assembly to the InteractiveAssemblyLoader..."); var dynamicGeneratedTypesReference = GenerateDynamicTypesAndExposeToScript(loader); options = options.AddReferences(dynamicGeneratedTypesReference); script = script.WithOptions(options); Console.WriteLine($"{Environment.NewLine}Now, we try to create an instance of 'DynamicGeneratedClass1' again in the script..."); script = script.ContinueWith("var instance = new DynamicGeneratedClass1();"); scriptState = await script.RunFromAsync(scriptState); Console.WriteLine($"...no error. Variable '{scriptState.Variables[3].Name}' with value '{scriptState.Variables[3].Value}' found in script result.{Environment.NewLine}"); Console.WriteLine("#########################################################################################"); Console.WriteLine(); Console.WriteLine($"{Environment.NewLine}Press any key to close window..."); Console.ReadKey(); }
public async Task <bool> InitScript(CancellationToken token = default) { using (await _scriptStateLock.LockAsync(token)) { if (_scriptState != null) { return(true); } try { var options = ScriptOptions.Default .WithReferences(_references.ToArrayLocked(_lockReferences)) .WithImports(_usings.ToArrayLocked(_lockUsings)); var globals = _globals.ToDictionaryLocked(_lockGlobals); if (globals.Any()) { var createGlobalsScript = CSharpScript.Create(CreateGlobalsType(), options); var image = createGlobalsScript.GetCompilation(); var stream = new MemoryStream(); var result = image.Emit(stream, cancellationToken: token); if (!result.Success) { var scriptResult = new ScriptResult { Result = string.Join("\n", result.Diagnostics.Select(d => d.GetMessage())), IsError = true }; Results.Add(scriptResult); ScriptResultReceived?.Invoke(this, scriptResult); return(false); } var imageArray = ImmutableArray.Create(stream.ToArray()); var portableReference = MetadataReference.CreateFromImage(imageArray); var libAssembly = Assembly.Load(imageArray.ToArray()); var globalsType = libAssembly.GetTypes().FirstOrDefault(t => t.Name == "ScriptGlobals"); var globalsInstance = Activator.CreateInstance(globalsType); foreach (var propInfo in globalsType.GetFields()) { propInfo.SetValue(globalsInstance, globals[propInfo.Name]); } using (var loader = new InteractiveAssemblyLoader()) { loader.RegisterDependency(libAssembly); var script = CSharpScript.Create(string.Empty, options.AddReferences(portableReference), globalsType, loader); _scriptState = await script.RunAsync(globalsInstance, cancellationToken : token); } } else { _scriptState = await CSharpScript.RunAsync(string.Empty, options, cancellationToken : token); } } catch (OperationCanceledException) { _scriptState = null; } } return(_scriptState != null); }
/// <summary> /// Create a new C# script. /// </summary> /// <param name="code">The source code of the script.</param> /// <param name="options">The script options.</param> /// <param name="allowSingleQuotes">Are single quoted literal strings in Macros allowed (true = VO compatible).</param> /// <param name="assemblyLoader">Custom assembly loader.</param> /// <typeparam name="T">The return type of the script</typeparam> public static T Compile <T>(string code, ScriptOptions options = null, bool allowSingleQuotes = true, InteractiveAssemblyLoader assemblyLoader = null) { Type globalsType = null; CancellationToken cancellationToken = default(CancellationToken); return(Script.CreateInitialScript <T>(XSharpMacroCompiler.GetInstance(allowSingleQuotes), SourceText.From(code, options?.FileEncoding), options, globalsType, assemblyLoader).RunAsync(null, cancellationToken).GetEvaluationResultAsync().Result); }
public abstract Script <T> CreateScript <T>(string code, ScriptOptions options, Type globalsTypeOpt, InteractiveAssemblyLoader assemblyLoader);
public override Script <T> CreateScript <T>(string code, ScriptOptions options, Type globalsTypeOpt, InteractiveAssemblyLoader assemblyLoader) { return(CSharpScript.Create <T>(code, options, globalsTypeOpt, assemblyLoader)); }
public Service() { // TODO (tomat): we should share the copied files with the host _metadataFileProvider = new MetadataShadowCopyProvider( Path.Combine(Path.GetTempPath(), "InteractiveHostShadow"), noShadowCopyDirectories: s_systemNoShadowCopyDirectories); _assemblyLoader = new InteractiveAssemblyLoader(_metadataFileProvider); _formattingOptions = new ObjectFormattingOptions( memberFormat: MemberDisplayFormat.Inline, quoteStrings: true, useHexadecimalNumbers: false, maxOutputLength: 200, memberIndentation: " "); _hostObject = new InteractiveHostObject(); var initialState = new EvaluationState( scriptState: null, scriptOptions: ScriptOptions.Default, sourceSearchPaths: ImmutableArray<string>.Empty, referenceSearchPaths: ImmutableArray<string>.Empty, workingDirectory: Directory.GetCurrentDirectory()); _lastTask = Task.FromResult(initialState); Console.OutputEncoding = Encoding.UTF8; // We want to be sure to delete the shadow-copied files when the process goes away. Frankly // there's nothing we can do if the process is forcefully quit or goes down in a completely // uncontrolled manner (like a stack overflow). When the process goes down in a controlled // manned, we should generally expect this event to be called. AppDomain.CurrentDomain.ProcessExit += HandleProcessExit; }
/// <summary> /// Create a new C# script. /// </summary> /// <param name="code">The source code of the script.</param> /// <param name="options">The script options.</param> /// <param name="globalsType">Type of global object.</param> /// <param name="assemblyLoader">Custom assembly loader.</param> /// <typeparam name="T">The return type of the script</typeparam> public static Script <T> Create <T>(string code, ScriptOptions options = null, Type globalsType = null, InteractiveAssemblyLoader assemblyLoader = null) { return(Script.CreateInitialScript <T>(CSharpScriptCompiler.Instance, code, options, globalsType, assemblyLoader)); }
public virtual ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var runtimeIdentitfer = GetRuntimeIdentitifer(); _logger.Verbose($"Current runtime is '{runtimeIdentitfer}'."); var opts = CreateScriptOptions(context); var runtimeId = RuntimeEnvironment.GetRuntimeIdentifier(); var inheritedAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(runtimeId).Where(x => x.FullName.StartsWith("system.", StringComparison.OrdinalIgnoreCase) || x.FullName.StartsWith("microsoft.codeanalysis", StringComparison.OrdinalIgnoreCase) || x.FullName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase)); foreach (var inheritedAssemblyName in inheritedAssemblyNames) { _logger.Verbose("Adding reference to an inherited dependency => " + inheritedAssemblyName.FullName); var assembly = Assembly.Load(inheritedAssemblyName); opts = opts.AddReferences(assembly); } var runtimeContext = File.Exists(Path.Combine(context.WorkingDirectory, Project.FileName)) ? ProjectContext.CreateContextForEachTarget(context.WorkingDirectory).FirstOrDefault() : null; if (runtimeContext == null) { _logger.Verbose("Unable to find project context for CSX files. Will default to non-context usage."); var scriptProjectProvider = ScriptProjectProvider.Create(new LoggerFactory()); var scriptProjectInfo = scriptProjectProvider.CreateProject(context.WorkingDirectory, "netcoreapp1.1"); runtimeContext = ProjectContext.CreateContextForEachTarget(scriptProjectInfo.PathToProjectJson).FirstOrDefault(); } _logger.Verbose($"Found runtime context for '{runtimeContext.ProjectFile.ProjectFilePath}'."); var projectExporter = runtimeContext.CreateExporter(context.Configuration); var runtimeDependencies = new HashSet <string>(); var projectDependencies = projectExporter.GetDependencies(); foreach (var projectDependency in projectDependencies) { var runtimeAssemblyGroups = projectDependency.RuntimeAssemblyGroups; foreach (var libraryAsset in runtimeAssemblyGroups.GetDefaultAssets()) { var runtimeAssemblyPath = libraryAsset.ResolvedPath; _logger.Verbose($"Discovered runtime dependency for '{runtimeAssemblyPath}'"); runtimeDependencies.Add(runtimeAssemblyPath); } foreach (var runtimeAssemblyGroup in runtimeAssemblyGroups) { if (!string.IsNullOrWhiteSpace(runtimeAssemblyGroup.Runtime) && runtimeAssemblyGroup.Runtime == runtimeIdentitfer) { foreach (var runtimeAsset in runtimeAssemblyGroups.GetRuntimeAssets(GetRuntimeIdentitifer())) { var runtimeAssetPath = runtimeAsset.ResolvedPath; _logger.Verbose($"Discovered runtime asset dependency ('{runtimeIdentitfer}') for '{runtimeAssetPath}'"); runtimeDependencies.Add(runtimeAssetPath); } } } } foreach (var runtimeDep in runtimeDependencies) { _logger.Verbose("Adding reference to a runtime dependency => " + runtimeDep); opts = opts.AddReferences(MetadataReference.CreateFromFile(runtimeDep)); } var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(context.Code.ToString(), opts, typeof(THost), loader); var orderedDiagnostics = script.GetDiagnostics(SuppressedDiagnosticIds); if (orderedDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { foreach (var diagnostic in orderedDiagnostics) { _logger.Log(diagnostic.ToString()); } throw new CompilationErrorException("Script compilation failed due to one or more errors.", orderedDiagnostics.ToImmutableArray()); } return(new ScriptCompilationContext <TReturn>(script, context.Code, loader)); }
public virtual ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var platformIdentifier = RuntimeHelper.GetPlatformIdentifier(); _logger.Verbose($"Current runtime is '{platformIdentifier}'."); var opts = CreateScriptOptions(context); var runtimeId = RuntimeEnvironment.GetRuntimeIdentifier(); var inheritedAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(runtimeId).Where(x => x.FullName.StartsWith("system.", StringComparison.OrdinalIgnoreCase) || x.FullName.StartsWith("microsoft.codeanalysis", StringComparison.OrdinalIgnoreCase) || x.FullName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase)); foreach (var inheritedAssemblyName in inheritedAssemblyNames) { _logger.Verbose("Adding reference to an inherited dependency => " + inheritedAssemblyName.FullName); var assembly = Assembly.Load(inheritedAssemblyName); opts = opts.AddReferences(assembly); } var pathToProjectJson = Path.Combine(context.WorkingDirectory, Project.FileName); IList <RuntimeDependency> runtimeDependencies = new List <RuntimeDependency>(); if (!File.Exists(pathToProjectJson)) { _logger.Verbose("Unable to find project context for CSX files. Will default to non-context usage."); var pathToCsProj = _scriptProjectProvider.CreateProject(context.WorkingDirectory); var dependencyResolver = new DependencyResolver(new CommandRunner(_logger), _logger); runtimeDependencies = dependencyResolver.GetRuntimeDependencies(pathToCsProj).ToList(); } else { _logger.Verbose($"Found runtime context for '{pathToProjectJson}'."); var dependencyResolver = new LegacyDependencyResolver(_logger); runtimeDependencies = dependencyResolver.GetRuntimeDependencies(pathToProjectJson).ToList(); } AssemblyLoadContext.Default.Resolving += (assemblyLoadContext, assemblyName) => MapUnresolvedAssemblyToRuntimeLibrary(runtimeDependencies.ToList(), assemblyLoadContext, assemblyName); foreach (var runtimeDep in runtimeDependencies) { _logger.Verbose("Adding reference to a runtime dependency => " + runtimeDep); opts = opts.AddReferences(MetadataReference.CreateFromFile(runtimeDep.Path)); } var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(context.Code.ToString(), opts, typeof(THost), loader); var orderedDiagnostics = script.GetDiagnostics(SuppressedDiagnosticIds); if (orderedDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { foreach (var diagnostic in orderedDiagnostics) { _logger.Log(diagnostic.ToString()); } throw new CompilationErrorException("Script compilation failed due to one or more errors.", orderedDiagnostics.ToImmutableArray()); } return(new ScriptCompilationContext <TReturn>(script, context.Code, loader)); }
protected abstract Script <T> Create <T>(string code, ScriptOptions options, Type globalsType, InteractiveAssemblyLoader assemblyLoader);
public async Task MissingRefrencesAutoResolution() { var portableLib = CSharpCompilation.Create( "PortableLib", new[] { SyntaxFactory.ParseSyntaxTree("public class C {}") }, new[] { SystemRuntimePP7Ref }, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); var portableLibRef = portableLib.ToMetadataReference(); var loader = new InteractiveAssemblyLoader(); loader.RegisterDependency(Assembly.Load(portableLib.EmitToArray().ToArray())); var s0 = await CSharpScript.Create("new C()", options: ScriptOptions.Default.AddReferences(portableLibRef), assemblyLoader: loader).RunAsync(); var c0 = s0.Script.GetCompilation(); // includes corlib, host type assembly by default: AssertEx.Equal(new[] { typeof(object).GetTypeInfo().Assembly.Location, "PortableLib" }, c0.ExternalReferences.SelectAsArray(m => m.Display)); // System.Runtime, 4.0.0.0 depends on all the assemblies below: AssertEx.Equal(new[] { "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "PortableLib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Data.SqlXml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", }, c0.GetBoundReferenceManager().GetReferencedAssemblies().Select(a => a.Value.Identity.GetDisplayName())); }
public void HostObjectInInMemoryAssembly() { var lib = CreateCompilationWithMscorlib("public class C { public int X = 1, Y = 2; }", "HostLib"); var libImage = lib.EmitToArray(); var libRef = MetadataImageReference.CreateFromImage(libImage); var libAssembly = Assembly.Load(libImage.ToArray()); var globalsType = libAssembly.GetType("C"); var globals = Activator.CreateInstance(globalsType); using (var loader = new InteractiveAssemblyLoader()) { loader.RegisterDependency(libAssembly); var script = CSharpScript.Create<int>( "X+Y", ScriptOptions.Default.WithReferences(libRef), globalsType: globalsType, assemblyLoader: loader); int result = script.RunAsync(globals).Result.ReturnValue; Assert.Equal(3, result); } }
public Service() { // TODO (tomat): we should share the copied files with the host _metadataFileProvider = new MetadataShadowCopyProvider( Path.Combine(Path.GetTempPath(), "InteractiveHostShadow"), noShadowCopyDirectories: s_systemNoShadowCopyDirectories); _assemblyLoader = new InteractiveAssemblyLoader(_metadataFileProvider); _formattingOptions = new ObjectFormattingOptions( memberFormat: MemberDisplayFormat.Inline, quoteStrings: true, useHexadecimalNumbers: false, maxOutputLength: 200, memberIndentation: " "); // We want to be sure to delete the shadow-copied files when the process goes away. Frankly // there's nothing we can do if the process is forcefully quit or goes down in a completely // uncontrolled manner (like a stack overflow). When the process goes down in a controlled // manned, we should generally expect this event to be called. AppDomain.CurrentDomain.ProcessExit += HandleProcessExit; }
public virtual ScriptCompilationContext <TReturn> CreateCompilationContext <TReturn, THost>(ScriptContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var platformIdentifier = RuntimeHelper.GetPlatformIdentifier(); Logger.Verbose($"Current runtime is '{platformIdentifier}'."); var runtimeDependencies = RuntimeDependencyResolver.GetDependencies(context.WorkingDirectory, context.ScriptMode, context.Code.ToString()).ToArray(); var opts = CreateScriptOptions(context, runtimeDependencies.ToList()); var runtimeId = RuntimeHelper.GetRuntimeIdentifier(); var inheritedAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(runtimeId).Where(x => x.FullName.StartsWith("microsoft.codeanalysis", StringComparison.OrdinalIgnoreCase)).ToArray(); // Build up a dependency map that picks runtime assembly with the highest version. // This aligns with the CoreCLR that uses the highest version strategy. var dependencyMap = runtimeDependencies.SelectMany(rtd => rtd.Assemblies).Distinct().GroupBy(rdt => rdt.Name.Name, rdt => rdt) .Select(gr => new { Name = gr.Key, ResolvedRuntimeAssembly = gr.OrderBy(rdt => rdt.Name.Version).Last() }) .ToDictionary(f => f.Name, f => f.ResolvedRuntimeAssembly, StringComparer.OrdinalIgnoreCase); foreach (var runtimeAssembly in dependencyMap.Values) { Logger.Verbose("Adding reference to a runtime dependency => " + runtimeAssembly); opts = opts.AddReferences(MetadataReference.CreateFromFile(runtimeAssembly.Path)); } foreach (var nativeAsset in runtimeDependencies.SelectMany(rtd => rtd.NativeAssets).Distinct()) { if (RuntimeHelper.IsWindows()) { LoadLibrary(nativeAsset); } } foreach (var inheritedAssemblyName in inheritedAssemblyNames) { // Always prefer the resolved runtime dependency rather than the inherited assembly. if (!dependencyMap.ContainsKey(inheritedAssemblyName.Name)) { Logger.Verbose($"Adding reference to an inherited dependency => {inheritedAssemblyName.FullName}"); var assembly = Assembly.Load(inheritedAssemblyName); opts = opts.AddReferences(assembly); } } AssemblyLoadContext.Default.Resolving += (assemblyLoadContext, assemblyName) => MapUnresolvedAssemblyToRuntimeLibrary(dependencyMap, assemblyLoadContext, assemblyName); // when processing raw code, make sure we inject new lines after preprocessor directives string code; if (context.FilePath == null) { var syntaxTree = CSharpSyntaxTree.ParseText(context.Code, ParseOptions); var syntaxRewriter = new PreprocessorLineRewriter(); var newSyntaxTree = syntaxRewriter.Visit(syntaxTree.GetRoot()); code = newSyntaxTree.ToFullString(); } else { code = context.Code.ToString(); } var loader = new InteractiveAssemblyLoader(); var script = CSharpScript.Create <TReturn>(code, opts, typeof(THost), loader); var orderedDiagnostics = script.GetDiagnostics(SuppressedDiagnosticIds); if (orderedDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { throw new CompilationErrorException("Script compilation failed due to one or more errors.", orderedDiagnostics.ToImmutableArray()); } return(new ScriptCompilationContext <TReturn>(script, context.Code, loader, opts)); }
internal Func <object, string> GetExec <T>(CsModPermission csScriptsAllowed, T rootObjectCompileTime, string script) where T : IScriptRootData { var messages = new List <string>(); bool success = true; MethodInfo mainMethod = null; Script <object> csScript = null; CsModPermission permissionNeeded; var rootCompileTime = rootObjectCompileTime as IScriptRootData; using (var loader = new InteractiveAssemblyLoader()) { var options = ScriptOptions.Default .WithAllowUnsafe(false) .WithEmitDebugInformation(false) .WithCheckOverflow(true) .WithOptimizationLevel(OptimizationLevel.Release) .WithImports(DefaultConfiguration.Current.Usings) .AddImports(Configuration.Current.Usings) .WithReferences(DefaultConfiguration.Current.AssemblyReferences) .AddReferences(Configuration.Current.AssemblyReferences) .AddReferences(typeof(EmpyrionScripting).Assembly.Location, typeof(IScriptRootData).Assembly.Location) .AddReferences(CustomAssemblies.Values.Select(A => A.LoadedAssembly)); csScript = CSharpScript.Create <object>(script, options, typeof(IScriptModData), loader); var compilation = csScript.GetCompilation(); var WhitelistDiagnosticAnalyzer = new WhitelistDiagnosticAnalyzer(DefaultConfiguration, Configuration); var analyzerCompilation = compilation .WithAnalyzers(ImmutableArray.Create <DiagnosticAnalyzer>(WhitelistDiagnosticAnalyzer)) .GetAnalysisResultAsync(CancellationToken.None) .GetAwaiter().GetResult().CompilationDiagnostics; analyzerCompilation.ForEach(A => AnalyzeDiagnostics(A.Value, messages, ref success)); if (WhitelistDiagnosticAnalyzer.ConfigurationIsChanged) { Configuration.Current.PrepareForSave(); Configuration.Save(); DefaultConfiguration.Current.PrepareForSave(); DefaultConfiguration.Save(); } permissionNeeded = WhitelistDiagnosticAnalyzer.PermissionNeeded; Assembly assembly = null; if (compilation.Assembly.TypeNames.Contains("ModMain")) { using (var assemblyStream = new MemoryStream()) { try { var result = compilation.Emit(assemblyStream); var resultSuccess = result.Success; if (resultSuccess) { assembly = Assembly.ReflectionOnlyLoad(assemblyStream.ToArray()); var callMainType = assembly.GetTypes().SingleOrDefault(MT => MT.Name == "ModMain"); mainMethod = callMainType.GetMethod("Main"); if (mainMethod != null) { assemblyStream.Seek(0, SeekOrigin.Begin); assembly = Assembly.Load(assemblyStream.ToArray()); callMainType = assembly.GetTypes().SingleOrDefault(MT => MT.Name == "ModMain"); mainMethod = callMainType.GetMethod("Main"); } } } catch (Exception loadError) { messages.Add($"Assembly:{loadError}"); } } } } if (messages.Count > 0) { Log?.Invoke($"C# Compile [{rootCompileTime.ScriptId}]:{string.Join("\n", messages)}", LogLevel.Error); if (EmpyrionScripting.Configuration.Current.ScriptTrackingError) { File.AppendAllText(rootObjectCompileTime is ScriptSaveGameRootData root ? EmpyrionScripting.GetTrackingFileName(root) : EmpyrionScripting.GetTrackingFileName(rootObjectCompileTime.E.GetCurrent(), rootObjectCompileTime.Script.GetHashCode().ToString()) + ".error", string.Join("\n", messages)); } } return(rootObject => { if (!success) { return string.Join("\n", messages); } var root = rootObject as IScriptRootData; if (csScriptsAllowed == CsModPermission.SaveGame && !(root is ScriptSaveGameRootData)) { return "C# scripts are only allowed in SaveGameScripts"; } if (csScriptsAllowed == CsModPermission.Admin && root.E.GetCurrent().Faction.Group != FactionGroup.Admin) { return "C# scripts are only allowed on admin structures"; } if (permissionNeeded == CsModPermission.SaveGame && !(root is ScriptSaveGameRootData)) { return "This script is only allowed in SaveGameScripts"; } if (permissionNeeded == CsModPermission.Admin && root.E.GetCurrent().Faction.Group != FactionGroup.Admin) { return "This script is only allowed on admin structures"; } string exceptionMessage = null; using (var output = new StringWriter()) { root.ScriptOutput = output; try { object result = null; if (mainMethod != null) { if (root.CsRoot is CsScriptFunctions csRoot) { csRoot.ScriptRoot = root; } result = mainMethod.Invoke(null, new[] { root as IScriptModData }); } else { result = csScript .RunAsync(root, ex => { exceptionMessage = $"Exception: {(root.IsElevatedScript ? ex.ToString() : ex.Message)}"; return true; }) .ConfigureAwait(true) .GetAwaiter() .GetResult() .ReturnValue; } if (result is Action action) { action(); } else if (result is Action <IScriptModData> simpleaction) { simpleaction(root); } else if (result is Func <IScriptModData, object> func) { output.Write(func(root)?.ToString()); } else if (result is Task task) { task.RunSynchronously(); } else { output.Write(result?.ToString()); } return exceptionMessage == null?output.ToString() : $"{exceptionMessage}\n\nScript output up to exception:\n{output}"; } catch (Exception error) { exceptionMessage = error.ToString(); return root.IsElevatedScript ? error.ToString() : error.Message; } finally { if (!string.IsNullOrEmpty(exceptionMessage)) { Log?.Invoke($"C# Run [{root.ScriptId}]:{exceptionMessage}\n{output}", LogLevel.Error); if (EmpyrionScripting.Configuration.Current.ScriptTrackingError) { File.AppendAllText(root is ScriptSaveGameRootData saveGameRoot ? EmpyrionScripting.GetTrackingFileName(saveGameRoot) : EmpyrionScripting.GetTrackingFileName(root.E.GetCurrent(), root.Script.GetHashCode().ToString()) + ".error", $"{exceptionMessage}\n\nScript output up to exception:\n{output}"); } } } } }); }