private void CompileAndCreateInstance(string program, string storage) { if (MySession.Static.EnableIngameScripts == false) { return; } m_wasTerminated = false; Assembly temp = null; MyGuiScreenEditor.CompileProgram(program, m_compilerErrors, ref temp); if (temp != null) { try { m_assembly = IlInjector.InjectCodeToAssembly("IngameScript_safe", temp, typeof(IlInjector).GetMethod("CountInstructions", BindingFlags.Public | BindingFlags.Static), typeof(IlInjector).GetMethod("CountMethodCalls", BindingFlags.Public | BindingFlags.Static)); var type = m_assembly.GetType("Program"); if (type != null) { IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); IlInjector.RestartCountingMethods(MAX_NUM_METHOD_CALLS); try { m_instance = Activator.CreateInstance(type) as IMyGridProgram; if (m_instance != null) { m_previousRunTimestamp = 0; m_instance.Storage = storage; m_instance.Me = this; m_instance.Echo = EchoTextToDetailInfo; } } catch (TargetInvocationException ex) { if (ex.InnerException != null) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.InnerException.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } } } catch (Exception ex) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } }
private void CompileAndCreateInstance(string program, string storage) { if (MySession.Static.EnableIngameScripts == false) { return; } m_terminationReason = ScriptTerminationReason.None; try { Assembly temp = null; MyGuiScreenEditor.CompileProgram(program, m_compilerErrors, ref temp); if (temp != null) { m_assembly = IlInjector.InjectCodeToAssembly("IngameScript_safe", temp, typeof(IlInjector).GetMethod("CountInstructions", BindingFlags.Public | BindingFlags.Static), typeof(IlInjector).GetMethod("CountMethodCalls", BindingFlags.Public | BindingFlags.Static)); var type = m_assembly.GetType("Program"); if (type != null) { m_instance = FormatterServices.GetUninitializedObject(type) as IMyGridProgram; var constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); string response; if (m_instance == null || constructor == null) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoValidConstructor); SetDetailedInfo(response); return; } m_runtime.Reset(); m_instance.Runtime = m_runtime; m_instance.Storage = storage; m_instance.Me = this; m_instance.Echo = EchoTextToDetailInfo; RunSandboxedProgramAction(p => { constructor.Invoke(p, null); if (!m_instance.HasMainMethod) { if (m_echoOutput.Length > 0) { response = m_echoOutput.ToString(); } response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain); OnProgramTermination(ScriptTerminationReason.NoEntryPoint); } }, out response); SetDetailedInfo(response); } } } catch (Exception ex) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; SetDetailedInfo(response); } }
private void CompileAndCreateInstance(string program, string storage) { if (MySession.Static.EnableIngameScripts == false) { return; } m_terminationReason = ScriptTerminationReason.None; try { if (MyFakes.ENABLE_ROSLYN_SCRIPTS) { #if !XB1 m_assembly = MyScriptCompiler.Static.Compile( MyApiTarget.Ingame, Path.Combine(MyFileSystem.UserDataPath, GetAssemblyName()), MyScriptCompiler.Static.GetIngameScript(program, "Program", typeof(MyGridProgram).Name), m_compilerMessages).Result; m_compilerErrors.Clear(); m_compilerErrors.AddRange(m_compilerMessages.Select(m => m.Text)); CreateInstance(m_assembly, m_compilerErrors, storage); #else // XB1 #if !XB1_SKIPASSERTFORNOW System.Diagnostics.Debug.Assert(false, "No scripts on XB1"); #endif // !XB1_SKIPASSERTFORNOW #endif // XB1 } else { Assembly temp = null; MyGuiScreenEditor.CompileProgram(program, m_compilerErrors, ref temp); if (temp != null) { #if !XB1 // XB1_NOILINJECTOR m_assembly = IlInjector.InjectCodeToAssembly("IngameScript_safe", temp, typeof(IlInjector).GetMethod("CountInstructions", BindingFlags.Public | BindingFlags.Static), typeof(IlInjector).GetMethod("CountMethodCalls", BindingFlags.Public | BindingFlags.Static)); #else // XB1 System.Diagnostics.Debug.Assert(false, "No scripts on XB1"); return; #endif // XB1 CreateInstance(m_assembly, m_compilerErrors, storage); } } } catch (Exception ex) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; SetDetailedInfo(response); } }
public override void Execute() { if (Environment.GetEnvironmentVariable("NOBSERVABLE_DEBUG_ATTACH") == "1") { LogError($"Attach debugger to {Process.GetCurrentProcess().Id}"); while (!Debugger.IsAttached) { Thread.Sleep(1000); } } var context = new WeavingContext(TypeSystem, this, ModuleDefinition); foreach (var t in AllTypes(ModuleDefinition.Types)) { var observeAll = t.CustomAttributes.Any(ca => ca.AttributeType.AreEqual(context.ObservableAttributeReference)); foreach (var p in t.Properties) { var getter = p.GetMethod; var setter = p.SetMethod; if (getter == null || setter == null) { continue; } if (getter.IsStatic || setter.IsStatic) { continue; } if (observeAll || p.CustomAttributes.Any(ca => ca.AttributeType.AreEqual(context.ObservableAttributeReference))) { IlInjector.InstrumentProperty(context, p); } } if (context.BlazorHelperAsm != null && IsBlazorComponent(t)) { if (t.Interfaces.Any(iface => iface.InterfaceType.FullName == "NObservable.Blazor.IObserverComponent")) { IlInjector.InstrumentBlazorComponent(context, t); } } } }
public override void Execute() { if (Environment.GetEnvironmentVariable("NOBSERVABLE_DEBUG_ATTACH") == "1") { LogError($"Attach debugger to {Process.GetCurrentProcess().Id}"); while (!Debugger.IsAttached) { Thread.Sleep(1000); } } var context = new WeavingContext(TypeSystem, ModuleDefinition); foreach (var t in AllTypes(ModuleDefinition.Types)) { var observeAll = t.CustomAttributes.Any(ca => ca.AttributeType.AreEqual(context.ObservableAttributeReference)); FieldReference field = null; if (t.Name.StartsWith("BasicEngineTest")) { var set = t.GetMethods().First(m => m.Name == "Wtf"); Console.WriteLine(); } foreach (var p in t.Properties) { var getter = p.GetMethod; var setter = p.SetMethod; if (getter == null || setter == null) { continue; } if (getter.IsStatic || setter.IsStatic) { continue; } if (observeAll || p.CustomAttributes.Any(ca => ca.AttributeType.AreEqual(context.ObservableAttributeReference))) { IlInjector.InstrumentProperty(context, p); } } } }
private void CompileAndCreateInstance(string program, string storage) { if (MySession.Static.EnableIngameScripts == false) { return; } m_wasTerminated = false; m_mainMethod = null; Assembly temp = null; MyGuiScreenEditor.CompileProgram(program, m_compilerErrors, ref temp); if (temp != null) { try { m_assembly = IlInjector.InjectCodeToAssembly("IngameScript_safe", temp, typeof(IlInjector).GetMethod("CountInstructions", BindingFlags.Public | BindingFlags.Static)); var type = m_assembly.GetType("Program"); if (type != null) { IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); try { m_instance = Activator.CreateInstance(type); m_programGridGroup = type.GetField("GridTerminalSystem", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_storageField = type.GetField("Storage", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_meField = type.GetField("Me", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_echoField = type.GetField("Echo", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); m_elapsedTimeField = type.GetField("ElapsedTime", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance); if (m_programGridGroup != null) { // First try to get the main method with a string argument. If this fails, try to get one without. m_mainMethod = type.GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(string) }, null); m_mainMethodSupportsArgument = m_mainMethod != null; if (m_mainMethod == null) { m_mainMethod = type.GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); } } if (m_storageField != null) { m_storageField.SetValue(m_instance, storage); } if (m_meField != null) { m_meField.SetValue(m_instance, this); } if (m_echoField != null) { m_echoField.SetValue(m_instance, new Action <string>(EchoTextToDetailInfo)); } } catch (TargetInvocationException ex) { if (ex.InnerException != null) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.InnerException.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } } } catch (Exception ex) { string response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; if (DetailedInfo.ToString() != response) { SyncObject.SendProgramResponseMessage(response); WriteProgramResponse(response); } } } }
public string ExecuteCode(string argument) { if (m_isRunning) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning)); } if (m_wasTerminated == true) { return(DetailedInfo.ToString()); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly)); } if (m_mainMethod == null) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain)); } if (this.m_elapsedTimeField != null) { if (m_previousRunTimestamp == 0) { m_previousRunTimestamp = Stopwatch.GetTimestamp(); m_elapsedTimeField.SetValue(m_instance, TimeSpan.Zero); } else { var currentTimestamp = Stopwatch.GetTimestamp(); var elapsedTime = (currentTimestamp - m_previousRunTimestamp) * Sync.RelativeSimulationRatio; m_elapsedTimeField.SetValue(m_instance, TimeSpan.FromSeconds(elapsedTime * STOPWATCH_FREQUENCY)); m_previousRunTimestamp = currentTimestamp; } } if (m_programGridGroup != null) { var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(CubeGrid); var terminalSystem = gridGroup.GroupData.TerminalSystem; terminalSystem.UpdateGridBlocksOwnership(this.OwnerId); m_programGridGroup.SetValue(m_instance, terminalSystem); } m_isRunning = true; string retVal = ""; IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); try { if (m_mainMethodSupportsArgument) { // Don't know if it's really necessary to predefine this argument array, I suspect not // due to the cleverness of the compiler, but I do it this way just in case. // Obviously if programmable block execution becomes asynchronous at some point this // must be reworked. m_argumentArray[0] = argument ?? string.Empty; m_mainMethod.Invoke(m_instance, m_argumentArray); } else { m_mainMethod.Invoke(m_instance, null); } if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } } catch (TargetInvocationException ex) { // Since we just had an exception I'm not fussed about using old // fashioned string concatenation here. We'll still want the echo // output, since its primary purpose is debugging. if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } OnProgramTermination(); if (ex.InnerException is ScriptOutOfRangeException) { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); } else if (ex.InnerException != null) { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.InnerException.Message; } } m_isRunning = false; return(retVal); }
public ScriptTerminationReason ExecuteCode(string argument, out string response) { if (m_isRunning) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning); return(ScriptTerminationReason.AlreadyRunning); } if (m_terminationReason != ScriptTerminationReason.None) { response = DetailedInfo.ToString(); return(m_terminationReason); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly); return(ScriptTerminationReason.NoScript); } if (!m_instance.HasMainMethod) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain); return(ScriptTerminationReason.NoEntryPoint); } if (m_previousRunTimestamp == 0) { m_previousRunTimestamp = Stopwatch.GetTimestamp(); m_instance.ElapsedTime = TimeSpan.Zero; } else { var currentTimestamp = Stopwatch.GetTimestamp(); var elapsedTime = (currentTimestamp - m_previousRunTimestamp) * Sync.RelativeSimulationRatio; m_instance.ElapsedTime = TimeSpan.FromSeconds(elapsedTime * STOPWATCH_FREQUENCY); m_previousRunTimestamp = currentTimestamp; } var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(CubeGrid); var terminalSystem = gridGroup.GroupData.TerminalSystem; terminalSystem.UpdateGridBlocksOwnership(this.OwnerId); m_instance.GridTerminalSystem = terminalSystem; m_isRunning = true; response = ""; try { using (IlInjector.BeginRunBlock(MAX_NUM_EXECUTED_INSTRUCTIONS, MAX_NUM_METHOD_CALLS)) { m_instance.Main(argument); } if (m_echoOutput.Length > 0) { response = m_echoOutput.ToString(); } } catch (Exception ex) { // Since we just had an exception I'm not fussed about using old // fashioned string concatenation here. We'll still want the echo // output, since its primary purpose is debugging. if (m_echoOutput.Length > 0) { response = m_echoOutput.ToString(); } if (ex is ScriptOutOfRangeException) { if (IlInjector.IsWithinRunBlock()) { // If we're within a nested run, we don't reset the program, we just pass the error response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NestedTooComplex); return(ScriptTerminationReason.InstructionOverflow); } else { response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); OnProgramTermination(ScriptTerminationReason.InstructionOverflow); } } else { response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; OnProgramTermination(ScriptTerminationReason.RuntimeException); } } finally { m_isRunning = false; } return(m_terminationReason); }
public string ExecuteCode(string argument) { if (m_isRunning) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning)); } if (m_wasTerminated == true) { return(DetailedInfo.ToString()); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly)); } if (!m_instance.HasMainMethod) { return(MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoMain)); } if (m_previousRunTimestamp == 0) { m_previousRunTimestamp = Stopwatch.GetTimestamp(); m_instance.ElapsedTime = TimeSpan.Zero; } else { var currentTimestamp = Stopwatch.GetTimestamp(); var elapsedTime = (currentTimestamp - m_previousRunTimestamp) * Sync.RelativeSimulationRatio; m_instance.ElapsedTime = TimeSpan.FromSeconds(elapsedTime * STOPWATCH_FREQUENCY); m_previousRunTimestamp = currentTimestamp; } var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(CubeGrid); var terminalSystem = gridGroup.GroupData.TerminalSystem; terminalSystem.UpdateGridBlocksOwnership(this.OwnerId); m_instance.GridTerminalSystem = terminalSystem; m_isRunning = true; string retVal = ""; IlInjector.RestartCountingInstructions(MAX_NUM_EXECUTED_INSTRUCTIONS); try { m_instance.Main(argument); if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } } catch (Exception ex) { // Since we just had an exception I'm not fussed about using old // fashioned string concatenation here. We'll still want the echo // output, since its primary purpose is debugging. if (m_echoOutput.Length > 0) { retVal = m_echoOutput.ToString(); } OnProgramTermination(); if (ex is ScriptOutOfRangeException) { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); } else { retVal += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; } } m_isRunning = false; return(retVal); }
public ScriptTerminationReason RunSandboxedProgramAction(Action <ModAPI.IMyGridProgram> action, out string response) { if (m_isRunning) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_AllreadyRunning); return(ScriptTerminationReason.AlreadyRunning); } if (m_terminationReason != ScriptTerminationReason.None) { response = DetailedInfo.ToString(); return(m_terminationReason); } DetailedInfo.Clear(); m_echoOutput.Clear(); if (m_assembly == null) { response = MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NoAssembly); return(ScriptTerminationReason.NoScript); } var gridGroup = MyCubeGridGroups.Static.Logical.GetGroup(CubeGrid); var terminalSystem = gridGroup.GroupData.TerminalSystem; terminalSystem.UpdateGridBlocksOwnership(this.OwnerId); m_instance.GridTerminalSystem = terminalSystem; m_isRunning = true; response = ""; #if !XB1 // XB1_NOILINJECTOR try { using (var handle = IlInjector.BeginRunBlock(MAX_NUM_EXECUTED_INSTRUCTIONS, MAX_NUM_METHOD_CALLS)) { m_runtime.InjectorHandle = handle; action(m_instance); } if (m_echoOutput.Length > 0) { response = m_echoOutput.ToString(); } return(m_terminationReason); } catch (Exception ex) { // Unwrap the exception if necessary if (ex is TargetInvocationException) { ex = ex.InnerException; } // Since we just had an exception I'm not fussed about using old // fashioned string concatenation here. We'll still want the echo // output, since its primary purpose is debugging. if (m_echoOutput.Length > 0) { response = m_echoOutput.ToString(); } if (ex is ScriptOutOfRangeException) { if (IlInjector.IsWithinRunBlock()) { // If we're within a nested run, we don't reset the program, we just pass the error response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_NestedTooComplex); return(ScriptTerminationReason.InstructionOverflow); } else { response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_TooComplex); OnProgramTermination(ScriptTerminationReason.InstructionOverflow); } } else { response += MyTexts.GetString(MySpaceTexts.ProgrammableBlock_Exception_ExceptionCaught) + ex.Message; OnProgramTermination(ScriptTerminationReason.RuntimeException); } return(m_terminationReason); } finally { m_runtime.InjectorHandle = null; m_isRunning = false; } #else // XB1 System.Diagnostics.Debug.Assert(false, "No scripts on XB1!"); return(m_terminationReason); #endif // XB1 }