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
        }