首页 > 代码库 > Unity 捕获IronPython脚本错误

Unity 捕获IronPython脚本错误

捕获的方法摘自《IronPython in Action》一书,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

using IronPython.Hosting;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Hosting;

using Plugins;


namespace EmbeddingPlugin
{
    internal class PythonStream: MemoryStream
    {
        TextBox _output;
        public PythonStream(TextBox textbox)
        {
            _output = textbox;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _output.AppendText(Encoding.UTF8.GetString(buffer, offset, count));
        }
    }

    internal class Engine
    {
        ScriptEngine _engine;
        ScriptRuntime _runtime;
        TextBox _box;

        public List<PluginBase> Plugins
        {
            get { return PluginStore.Plugins; }
        }


        public Engine(TextBox textbox)
        {
            _engine = Python.CreateEngine();
            _runtime = _engine.Runtime;
            _box = textbox;

            SetStreams();
            string rootDir = AddAssemblies();
            LoadPlugins(rootDir);
        }

        public void SetStreams()
        {
            PythonStream stream = new PythonStream(_box);
            _runtime.IO.SetOutput(stream, Encoding.UTF8);
            _runtime.IO.SetErrorOutput(stream, Encoding.UTF8);
        }

        public string AddAssemblies()
        {
            Assembly mainAssembly = Assembly.GetExecutingAssembly();

            string rootDir = Directory.GetParent(mainAssembly.Location).FullName;
            string pluginsPath = Path.Combine(rootDir, "Plugins.dll");

            Assembly pluginsAssembly = Assembly.LoadFile(pluginsPath);

            _runtime.LoadAssembly(mainAssembly);
            _runtime.LoadAssembly(pluginsAssembly);
            _runtime.LoadAssembly(typeof(String).Assembly);
            _runtime.LoadAssembly(typeof(Uri).Assembly);

            return rootDir;
        }

        public void LoadPlugins(string rootDir)
        {
            string pluginsDir = Path.Combine(rootDir, "plugins");
            foreach (string path in Directory.GetFiles(pluginsDir))
            {
                if (path.ToLower().EndsWith(".py"))
                {
                    CreatePlugin(path);
                }
            }
        }

        public void CreatePlugin(string path)
        {
            try
            {
                ScriptSource script = _engine.CreateScriptSourceFromFile(path);
                CompiledCode code = script.Compile();
                ScriptScope scope = _engine.CreateScope();
                script.Execute(scope);
            }
            catch (SyntaxErrorException e)
            {
                string msg = "Syntax error in \"{0}\"";
                ShowError(msg, Path.GetFileName(path), e);
            }
            catch (SystemExitException e)
            {
                string msg = "SystemExit in \"{0}\"";
                ShowError(msg, Path.GetFileName(path), e);
            }

            catch (Exception e)
            {
                string msg = "Error loading plugin \"{0}\"";
                ShowError(msg, Path.GetFileName(path), e);
            }
        }

        public void ShowError(string title, string name, Exception e)
        {
            string caption = String.Format(title, name);
            ExceptionOperations eo = _engine.GetService<ExceptionOperations>();
            string error = eo.FormatException(e);
            MessageBox.Show(error, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);

        }

        public void ExecutePluginAtIndex(int index)
        {
            PluginBase plugin = Plugins[index];

            try
            {
                plugin.Execute(_box);
            }
            catch (Exception e)
            {
                string msg = "Error executing plugin \"{0}\"";
                ShowError(msg, plugin.Name, e);
            }
        }
    }
}

结果如:

移植到Unity中,则只取关键性代码即可。