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