예제 #1
0
            public ReturnCode Run()
            {
                //暫存運算結果
                string val;

                //如果運算成功就寫入變量的值
                //回傳空白的返回碼
                if (ExprParser.TryParse(expr, out val))
                {
                    //如果是反應設定
                    if (ID == "$WAITFORRESP" && val.ToUpper() == "FALSE")
                    {
                        Internals.Execute("MAKERESP", "");
                        return(new ReturnCode("", ""));
                    }

                    //寫入變量
                    Variables.Write(ID, val);

                    return(new ReturnCode("", ""));
                }
                //失敗的話就回傳錯誤信息
                else
                {
                    return(new ReturnCode("ERR", expr + Localization.GetMessage("INVALIDEXPR", " is not a valid expression.") + " [MUTAN, " + ID + "=" + expr + "]"));
                }
            }
예제 #2
0
            public ReturnCode Run()
            {
                //暫存內容
                string arg = "";

                foreach (string line in content)
                {
                    //每一句用 /n 分隔
                    arg += line + "\n";
                }
                //利用 WAITFORRESP 指令等待回應然後執行反應
                Internals.Execute("WAITFORRESP", arg);
                return(new ReturnCode("", ""));
            }
예제 #3
0
        //從檔案讀取變量
        static public void Load(string filePath)
        {
            if (File.Exists(filePath))
            {
                //用來記錄當前行數
                int numLine = 1;

                //暫存當前這行的內容
                string[] entry;

                //暫存解析出來的 ID
                string ID;

                //逐行讀取
                foreach (string line in File.ReadAllLines(filePath))
                {
                    try
                    {
                        //如果是空白行或注解就跳過, 否則進行解析
                        if (line.Trim() != "" && !line.StartsWith("#"))
                        {
                            entry = line.Trim().Split('=');
                            ID    = entry[0];

                            //寫入變量環境
                            Write(ID.Trim(), line.Replace(ID + "=", "").Trim());
                        }
                    }
                    catch
                    {
                        //如果解析失敗代表格式有問題
                        Internals.ERROR(Localization.GetMessage("ILLFORMAT", "Ill-formatted data in line {arg}", numLine.ToString()) + " [" + filePath + "]");
                    }

                    //更新當前行數
                    numLine++;
                }
            }
        }
예제 #4
0
        //執行循環
        void RunScript()
        {
            //如果不是要中斷的話就一直重覆
            while (!BREAKING)
            {
                //執行物件, 取得返回碼
                MUTAN.ReturnCode tmp = obj.Run();

                //如果是 BREAK 指令, 就設 BREAK 為真, 退出循環
                if (tmp.Command.Trim() == "BREAK")
                {
                    BREAKING = true;
                    break;
                }
                //否則就執行指令
                else
                {
                    Internals.Execute(tmp.Command, tmp.Argument);
                }
            }

            //如果循環結束了就中斷線程
            Break();
        }
예제 #5
0
            public ReturnCode Run()
            {
                //如果參數是空白,就直接執行, 不必運算參數
                if (arg.Trim() == "")
                {
                    Internals.Execute(RID, "");
                    return(new ReturnCode("", ""));
                }

                //否則就要對參數進行運數

                //暫存運算結果
                string val;

                //如果失敗的話就回傳錯誤信息
                if (!ExprParser.TryParse(arg, out val))
                {
                    return(new ReturnCode("ERR", arg + Localization.GetMessage("INVALIDEXPR", " is not a valid expression.") + "[MUTAN, " + RID + "(" + arg + ")]"));
                }

                //否則就執行
                Internals.Execute(RID, val);
                return(new ReturnCode("", ""));
            }
예제 #6
0
 public AZUSAAppContext()
 {
     //初始化
     Internals.INIT();
 }
예제 #7
0
        //執行指令
        static public void Execute(string cmd, string arg)
        {
            //如果是空白指令就直接無視掉就行
            if (cmd.Trim() == "")
            {
                return;
            }

            //Internal commands
            switch (cmd)
            {
            // DEBUG() 開關除錯模式
            case "DEBUG":
                Debugging = !Debugging;
                MESSAGE(Localization.GetMessage("DEBUG", "Entered debug mode. AZUSA will display all errors and listen to all commands."));
                Variables.Write("$SYS_DEBUG", Debugging.ToString());
                break;

            // BROADCAST({expr}) 向所有引擎廣播消息
            case "BROADCAST":
                ProcessManager.Broadcast(arg);
                break;

            // EXIT() 退出程序
            case "EXIT":
                //創建一個負責退出的線程
                new Thread(new ThreadStart(EXIT)).Start();
                break;

            // RESTART() 重啟程序
            case "RESTART":
                //創建一個負責重啟的線程
                new Thread(new ThreadStart(RESTART)).Start();
                break;

            // WAIT({int}) 暫停線程
            case "WAIT":
                System.Threading.Thread.Sleep(Convert.ToInt32(arg));
                break;

            // ACTVIEW() 打開活動檢視器
            case "ACTVIEW":
                itmActivity_Click(null, EventArgs.Empty);
                break;

            // PRCMON() 打開進程檢視器
            case "PRCMON":
                itmMonitor_Click(null, EventArgs.Empty);
                break;

            // EXEC(filepath,IsApp) 創建進程
            case "EXEC":
                string patharg = arg.Replace("{AZUSA}", Environment.CurrentDirectory);

                // Get the second arg (true/false) indicating whether process should be executed through AZUSA
                bool thruAZUSA = true;
                if (patharg.Contains(','))
                {
                    Boolean.TryParse(patharg.Split(',').Last(), out thruAZUSA);
                }

                patharg = patharg.Trim();
                string path = patharg;
                string Arg  = "";
                if (patharg.Contains('$'))
                {
                    path = patharg.Split('$')[0];
                    Arg  = patharg.Replace(path + "$", "");
                }
                if (path.EndsWith(".exe") && thruAZUSA)
                {
                    ProcessManager.AddProcess(Path.GetFileNameWithoutExtension(path), path, Arg);
                }
                else
                {
                    try
                    {
                        System.Diagnostics.Process target = new System.Diagnostics.Process();
                        target.StartInfo.FileName         = path;
                        target.StartInfo.Arguments        = arg;
                        target.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(path);
                        target.Start();
                    }
                    catch
                    {
                        Internals.ERROR(Localization.GetMessage("ENGSTARTFAIL", "Unable to run {arg}. Please make sure it is in the correct folder.", path));
                    }
                }

                break;

            // KILL(prcName) 終止進程
            case "KILL":
                ProcessManager.Kill(arg);
                break;

            // SCRIPT({SID(.part)},arg1=val1,arg2=val2,...) 執行腳本檔
            case "SCRIPT":
                //創建執行物件
                MUTAN.IRunnable obj;

                //解析參數
                string[] parsed = Utils.SplitWithProtection(arg).ToArray();

                //分割參數, 以便取得部分名, 例如 TEST.part1
                string[] scr = parsed[0].Split('.');

                List <string> var = new List <string>();
                List <string> val = new List <string>();

                //處理傳入值
                for (int i = 1; i < parsed.Count(); i++)
                {
                    var.Add(Utils.LSplit(parsed[i], "="));
                    val.Add(Utils.RSplit(parsed[i], "="));
                }

                //用來暫存腳本內容的陣列
                string[] program;

                //首先嘗試讀入腳本內容
                var scriptpath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Scripts\" + scr[0];
                if (File.Exists(scriptpath + ".mut"))
                {
                    program = File.ReadAllLines(scriptpath + ".mut");
                }
                else if (File.Exists(scriptpath + ".msf"))
                {
                    program = File.ReadAllLines(scriptpath + ".msf");
                }
                else
                {
                    Internals.ERROR(Localization.GetMessage("SCRMISSING", "Unable to find the script named {arg}. Please make sure it is in the correct folder.", scr[0]));
                    return;
                }


                //如果有分塊的話, 就先進行提取
                if (scr.Length > 1)
                {
                    for (int i = 1; i < scr.Length; i++)
                    {
                        program = MUTAN.GetPart(program, scr[i]);
                    }
                }

                //取代傳入值
                for (int ln = 0; ln < program.Count(); ln++)
                {
                    for (int i = 0; i < var.Count(); i++)
                    {
                        program[ln] = program[ln].Replace("{" + var[i] + "}", val[i]);
                    }
                }


                //然後進行解析
                MUTAN.Parser.TryParse(program, out obj);

                //清理暫存
                program = null;

                //解析結果不為空的話就執行
                //否則就報錯
                if (obj != null)
                {
                    MUTAN.ReturnCode tmp = obj.Run();

                    if (tmp.Command != "END")
                    {
                        Execute(tmp.Command, tmp.Argument);
                    }


                    //扔掉物件
                    obj = null;
                }
                else
                {
                    ERROR(Localization.GetMessage("SCRERROR", "An error occured while running script named {arg}. Please make sure there is no syntax error.", scr[0]));
                }
                break;

            //等待回應
            case "WAITFORRESP":
                //把 $WAITFORRESP 設成 TRUE
                Variables.Write("$WAITFORRESP", "TRUE");
                ////通知引擎 (主要是針對 AI) 現在正等待回應
                ProcessManager.Broadcast("EVENT(WaitingForResp)");

                respCache = arg;
                break;

            // MAKERESP(resp) 作出反應
            case "MAKERESP":
                //把 $WAITFORRESP 設成 FALSE
                Variables.Write("$WAITFORRESP", "FALSE");
                Variables.Write("$RESP", arg);

                if (respCache == "")
                {
                    break;
                }

                ////通知引擎已作出反應
                //ProcessManager.Broadcast("RESPONDED");

                //解析暫存
                MUTAN.Parser.TryParse(respCache.Split('\n'), out obj);

                //清空暫存
                respCache = "";

                //解析結果不為空的話就執行
                //否則就報錯
                if (obj != null)
                {
                    MUTAN.ReturnCode tmp = obj.Run();

                    if (tmp.Command != "END")
                    {
                        Execute(tmp.Command, tmp.Argument);
                    }

                    //扔掉物件
                    obj = null;
                }
                else
                {
                    ERROR(Localization.GetMessage("SCRERROR", "An error occured while running a response script. Please make sure there is no syntax error. [MUTAN, " + respCache + "]"));
                }
                break;

            // ERR({expr}) 發送錯誤信息
            case "ERR":
                //ERR 是屬於表現層的系統指令, 容許被接管
                bool routed = false;

                List <IOPortedPrc> ListCopy = new List <IOPortedPrc>(ProcessManager.GetCurrentProcesses());

                //檢查每一個現在運行中的進程
                foreach (IOPortedPrc prc in ListCopy)
                {
                    try
                    {
                        //如果進程有接管這個指令, 就把指令內容傳過去
                        if (prc.RIDs.ContainsKey(cmd))
                        {
                            //設 routed 為 true
                            routed = true;

                            //根據 RIDs 的值,決定只傳參數還是指令跟參數整個傳過去
                            //RIDs 的值如果是 true 的話就表示只傳參數
                            if (prc.RIDs[cmd])
                            {
                                prc.WriteLine(arg);
                            }
                            else
                            {
                                prc.WriteLine(cmd + "(" + arg + ")");
                            }
                        }
                    }
                    catch { }
                }

                //扔掉 ListCopy
                ListCopy = null;

                //否則就由圖標發出提示
                if (!routed)
                {
                    ERROR(arg);
                }
                break;

            // MSG({expr}) 發送信息
            case "MSG":
                //MSG 是屬於表現層的系統指令, 容許被接管
                routed = false;

                ListCopy = new List <IOPortedPrc>(ProcessManager.GetCurrentProcesses());

                //檢查每一個現在運行中的進程
                foreach (IOPortedPrc prc in ListCopy)
                {
                    try
                    {
                        //如果進程有接管這個指令, 就把指令內容傳過去
                        if (prc.RIDs.ContainsKey(cmd))
                        {
                            //設 routed 為 true
                            routed = true;

                            //根據 RIDs 的值,決定只傳參數還是指令跟參數整個傳過去
                            //RIDs 的值如果是 true 的話就表示只傳參數
                            if (prc.RIDs[cmd])
                            {
                                prc.WriteLine(arg);
                            }
                            else
                            {
                                prc.WriteLine(cmd + "(" + arg + ")");
                            }
                        }
                    }
                    catch { }
                }

                //扔掉 ListCopy
                ListCopy = null;

                //否則就由圖標發出提示
                if (!routed)
                {
                    MESSAGE(arg);
                }
                break;

            // MENU(name, script) 添加右鍵選單項目
            case "MENU":
                parsed = arg.Split(',');
                Internals.ADDMENUITEM(parsed[0].Trim(), arg.Replace(parsed[0] + ",", "").Trim());
                break;

            default:
                //如果不是系統指令, 先檢查是否有引擎登記接管了這個指令
                // routed 記錄指令是否已被接管
                routed = false;

                ListCopy = new List <IOPortedPrc>(ProcessManager.GetCurrentProcesses());

                //檢查每一個現在運行中的進程
                foreach (IOPortedPrc prc in ListCopy)
                {
                    try
                    {
                        //如果進程有接管這個指令, 就把指令內容傳過去
                        if (prc.RIDs.ContainsKey(cmd))
                        {
                            //設 routed 為 true
                            routed = true;

                            //根據 RIDs 的值,決定只傳參數還是指令跟參數整個傳過去
                            //RIDs 的值如果是 true 的話就表示只傳參數
                            if (prc.RIDs[cmd])
                            {
                                prc.WriteLine(arg);
                            }
                            else
                            {
                                prc.WriteLine(cmd + "(" + arg + ")");
                            }
                        }
                    }
                    catch { }
                }

                //扔掉 ListCopy
                ListCopy = null;

                //所有進程都檢查完畢
                //如果 routed 為 true, 那麼已經有進程接管了, AZUSA 就可以不用繼續執行
                //No need to continue executing the command because it has been routed already
                if (!routed)
                {
                    //否則的話就當成函式呼叫, 如果有註明副檔名的就根據副檔名執行
                    if (cmd.Contains('.'))
                    {
                        switch (cmd.Split('.')[1])
                        {
                        case "bat":
                            ProcessManager.AddProcess(cmd, "cmd.exe", "/C \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + "\" " + arg);
                            return;

                        case "cmd":
                            ProcessManager.AddProcess(cmd, "cmd.exe", "/C \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + "\" " + arg);
                            return;

                        case "vbs":
                            ProcessManager.AddProcess(cmd, "cscript.exe", " \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + "\" " + arg);
                            return;
                        }
                    }

                    //如果沒副檔名就先找 exe
                    if (!ProcessManager.AddProcess(cmd, Environment.CurrentDirectory + @"\Routines\" + cmd + ".exe", arg))
                    {
                        //再找 bat (利用 bat 可以呼叫基本上任何直譯器調用任何腳本語言了)
                        if (File.Exists(Environment.CurrentDirectory + @"\Routines\" + cmd + ".bat"))
                        {
                            ActivityLog.Add("Calling \"" + "cmd.exe " + "/C \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + ".bat\" " + arg + "\"");
                            ProcessManager.AddProcess(cmd, "cmd.exe", "/C \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + ".bat\" " + arg);
                        }
                        //再找 cmd
                        else if (File.Exists(Environment.CurrentDirectory + @"\Routines\" + cmd + ".cmd"))
                        {
                            ActivityLog.Add("Calling \"" + "cmd.exe " + "/C \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + ".cmd\" " + arg + "\"");
                            ProcessManager.AddProcess(cmd, "cmd.exe", "/C \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + ".cmd\" " + arg);
                            //再找 vbs
                        }
                        else if (File.Exists(Environment.CurrentDirectory + @"\Routines\" + cmd + ".vbs"))
                        {
                            ProcessManager.AddProcess(cmd, "cscript.exe", " \"" + Environment.CurrentDirectory + @"\Routines\" + cmd + ".vbs\" " + arg);
                            //都找不到就報錯
                        }
                        else
                        {
                            ERROR(Localization.GetMessage("ENGSTARTFAIL", "Unable to run {arg}. Please make sure it is in the correct folder.", cmd));
                        }
                    }
                }
                break;
            }
        }
예제 #8
0
        //初始化
        static public void INIT()
        {
            //從 DATA 載入所有已儲存的變量
            //Load all the variables
            Variables.Load(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\DATA");

            Variables.Write("$SYS_READY", "FALSE");

            //載入提示信息
            Localization.Initialize();

            //創建提示圖標
            //Set up notify icon
            notifyIcon.Icon         = AZUSA.Properties.Resources.icon;
            notifyIcon.Visible      = true;
            notifyIcon.DoubleClick += new EventHandler(notifyIcon_DoubleClick);

            //創建圖標右擊菜單的項目
            MenuItem itmMonitor = new MenuItem(Localization.GetMessage("PRCMON", "Process Monitor")); //進程監視器

            itmMonitor.Click += new EventHandler(itmMonitor_Click);
            MenuItem itmActivity = new MenuItem(Localization.GetMessage("ACTMON", "Activity Monitor")); //活動監視器

            itmActivity.Click += new EventHandler(itmActivity_Click);
            MenuItem itmRELD = new MenuItem(Localization.GetMessage("RELOAD", "Reload")); //重新載入

            itmRELD.Click += new EventHandler(itmRELD_Click);
            MenuItem itmEXIT = new MenuItem(Localization.GetMessage("EXIT", "Exit")); //退出

            itmEXIT.Click += new EventHandler(itmEXIT_Click);
            MenuItem sep = new MenuItem("-");

            ContextMenu menu = new ContextMenu(new MenuItem[] { itmMonitor, itmActivity, sep, itmRELD, itmEXIT });

            //把圖標右擊菜單設成上面創建的菜單
            notifyIcon.ContextMenu = menu;

            //搜索 Engines\ 底下的所有執行檔, SearchOption.AllDirectories 表示子目錄也在搜索範圍內
            //Start the engines
            string EngPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\Engines";

            string[] EngList = new string[] { };
            if (Directory.Exists(EngPath))
            {
                EngList = System.IO.Directory.GetFiles(EngPath, "*.exe", SearchOption.TopDirectoryOnly);
            }
            else
            {
                ERROR(Localization.GetMessage("ENGPATHMISSING", "The \\Engines folder is missing. AZUSA will not be able to perform any function without suitable engines."));

                return;
            }

            //提示本體啟動成功, 待各引擎啟動完畢後會再有提示的
            //MESSAGE(Localization.GetMessage("AZUSAREADY", "AZUSA is ready. Waiting for engines to initialize..."));

            //每一個執行檔都添加為引擎
            foreach (string exePath in EngList)
            {
                //如果不成功就發錯誤信息
                if (!ProcessManager.AddProcess(exePath.Replace(EngPath + @"\", "").Replace(".exe", "").Trim(), exePath))
                {
                    Internals.ERROR(Localization.GetMessage("ENGSTARTFAIL", "Unable to run {arg}. Please make sure it is in the correct folder.", exePath.Replace(EngPath + @"\", "").Replace(".exe", "").Trim()));
                }
            }
        }
예제 #9
0
        //處理引擎的輸出
        void Engine_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            string Data = Utils.UriDecode(e.Data);

            //如果是空白輸出, 不要理會
            //Ignore NULL and empty inputs that will crash the program
            if (Data == null || Data.Trim() == "")
            {
                return;
            }

            //activity log
            ActivityLog.Add("From " + Name + ": " + Data);

            //如果是詢問, 則調用 MUTAN 表達式解析器, 並返回結東
            //詢問的語法是 "(表達式)?"
            //First check if the engine is asking a question about value of an expression
            if (Data.EndsWith("?"))
            {
                //首先保護進程以免受到 BROADCAST 干擾
                NoBroadcast = true;

                string result;

                //去掉最後的問號, 就是表達式了
                //如果格式有誤的話, 會返回 INVALIDEXPR (無效的表達式) 或 IMBALBRACKET (括號不平衡)
                MUTAN.ExprParser.TryParse(Data.TrimEnd('?'), out result);
                Engine.StandardInput.WriteLine(result);

                //解除 BROADCAST 干擾保護
                NoBroadcast = false;

                //activity log
                ActivityLog.Add("To " + Name + ": " + result);

                return;
            }

            string RID = "";
            string arg = "";

            //首先假設是溝通用的指令, 主要是用來讓進程宣佈自己的角色和功能, 並取得可用接口等等的溝通協調用的指令
            //對字串分割並去掉多餘空白
            if (MUTAN.IsExec(Data))
            {
                RID = Data.Split('(')[0];
                arg = Data.Substring(RID.Length + 1, Data.Length - RID.Length - 2);
                RID = RID.Trim();
            }


            switch (RID)
            {
            //這是用來進入除錯模式的, 除錯模式下不會要求完備性
            case "DEBUG":
                Internals.Debugging = true;
                Variables.Write("$SYS_DEBUG", "TRUE");
                Internals.MESSAGE(Localization.GetMessage("DEBUG", "Entered debug mode. AZUSA will display all errors and listen to all commands."));
                return;

            //進行回傳
            case "Return":
                output    = arg;
                RESPONDED = true;
                return;

            //這是用來讓進程取得 AZUSA 的 pid, 進程可以利用 pid 檢查 AZUSA 是否存活, 當 AZUSA 意外退出時, 進程可以檢查到並一併退出
            case "GetAzusaPid":

                //首先保護進程以免受到 BROADCAST 干擾
                NoBroadcast = true;

                Engine.StandardInput.WriteLine(Process.GetCurrentProcess().Id);
                //activity log
                ActivityLog.Add("To " + Name + ": " + Process.GetCurrentProcess().Id);

                //解除 BROADCAST 干擾保護
                NoBroadcast = false;

                return;

            //這是讓進程宣佈自己的身份的, 這指令應該是進程完成各種初始化之後才用的
            case "RegisterAs":
                //先記錄現在是否完備
                bool tmp = ProcessManager.CheckCompleteness();

                //然後進行相應的登錄
                switch (arg)
                {
                case "AI":
                    currentType = PortType.AI;
                    ProcessManager.AIPid.Add(pid);
                    break;

                case "Input":
                    currentType = PortType.Input;
                    ProcessManager.InputPid.Add(pid);
                    break;

                case "Output":
                    currentType = PortType.Output;
                    ProcessManager.OutputPid.Add(pid);
                    break;

                case "Application":
                    currentType = PortType.Application;
                    break;

                default:
                    break;
                }

                //再次檢查完備性, 如果之前不完備, 現在完備了就進行提示
                if (!tmp && ProcessManager.CheckCompleteness())
                {
                    Internals.READY();
                }

                return;

            //這是讓進程宣佈自己的可連接的接口, AZUSA 記錄後可以轉告其他進程, 進程之間可以直接對接而不必經 AZUSA
            case "RegisterPort":
                ProcessManager.Ports.Add(arg.Trim('"'), currentType);
                this.Ports.Add(arg.Trim('"'));
                ProcessManager.Broadcast("PortHasChanged");
                return;

            //這是讓進程取得當前可用所有端口
            case "GetAllPorts":

                //首先保護進程以免受到 BROADCAST 干擾
                NoBroadcast = true;

                string result = "";
                foreach (KeyValuePair <string, PortType> port in ProcessManager.Ports)
                {
                    result += port.Key + ",";
                }

                Engine.StandardInput.WriteLine(result.Trim(','));

                //解除 BROADCAST 干擾保護
                NoBroadcast = false;

                //activity log
                ActivityLog.Add("To " + Name + ": " + result.Trim(','));

                return;

            //這是讓進程取得當前可用的AI 端口(AI引擎的接口)
            case "GetAIPorts":

                //首先保護進程以免受到 BROADCAST 干擾
                NoBroadcast = true;

                result = "";
                foreach (KeyValuePair <string, PortType> port in ProcessManager.Ports)
                {
                    if (port.Value == PortType.AI)
                    {
                        result += port.Key + ",";
                    }
                }

                Engine.StandardInput.WriteLine(result.Trim(','));

                //解除 BROADCAST 干擾保護
                NoBroadcast = false;

                //activity log
                ActivityLog.Add("To " + Name + ": " + result.Trim(','));

                return;

            //這是讓進程取得當前可用的輸入端口(輸入引擎的接口)
            case "GetInputPorts":

                //首先保護進程以免受到 BROADCAST 干擾
                NoBroadcast = true;

                result = "";
                foreach (KeyValuePair <string, PortType> port in ProcessManager.Ports)
                {
                    if (port.Value == PortType.Input)
                    {
                        result += port.Key + ",";
                    }
                }

                Engine.StandardInput.WriteLine(result.Trim(','));

                //解除 BROADCAST 干擾保護
                NoBroadcast = false;

                //activity log
                ActivityLog.Add("To " + Name + ": " + result.Trim(','));

                return;

            //這是讓進程取得當前可用的輸出端口(輸出引擎的接口)
            case "GetOutputPorts":

                //首先保護進程以免受到 BROADCAST 干擾
                NoBroadcast = true;

                result = "";
                foreach (KeyValuePair <string, PortType> port in ProcessManager.Ports)
                {
                    if (port.Value == PortType.Output)
                    {
                        result += port.Key + ",";
                    }
                }

                Engine.StandardInput.WriteLine(result.Trim(','));

                //解除 BROADCAST 干擾保護
                NoBroadcast = false;

                //activity log
                ActivityLog.Add("To " + Name + ": " + result.Trim(','));

                return;

            //這是讓進程可以宣佈自己責負甚麼函式, AZUSA 在接收到這種函件就會轉發給進程
            //函式接管不是唯一的, 可以同時有多個進程接管同一個函式, AZUSA 會每個宣告了接管的進程都轉發一遍
            case "LinkRID":
                string[] parsed = arg.Split(',');

                this.RIDs.Add(parsed[0], Convert.ToBoolean(parsed[1]));

                return;

            default:
                break;
            }

            //檢查整體架構是否完備, 完備或除錯模式下才執行指令
            if (Internals.SysReady || Internals.Debugging)
            {
                //否則假設是 MUTAN 指令,嘗試解析, 如果失敗的話, 就無視掉本次輸出

                //先創建一個可運行物件, 用來儲存解析結果
                MUTAN.IRunnable obj;


                //然後用單行解析器
                if (MUTAN.LineParser.TryParse(Data, out obj))
                {
                    //如果成功解析, 則運行物件, 獲取回傳碼
                    MUTAN.ReturnCode tmp = obj.Run();

                    //然後按回傳碼執行指令
                    if (tmp.Command != "")
                    {
                        Internals.Execute(tmp.Command, tmp.Argument);
                    }
                }
            }
            else
            {
                Internals.ERROR(Localization.GetMessage("ENGINEMISSING", "Some engines are missing. AZUSA will not execute any MUTAN commands unless AI and I/O are all registered."));
            }
        }
예제 #10
0
        //對進程自行退出的事件處理
        void Engine_Exited(object sender, EventArgs e)
        {
            //首先暫停處理引擎的輸出
            Pause();

            //如果是負責接口的話
            if (Ports.Count != 0)
            {
                foreach (string port in Ports)
                {
                    //取消掉所有接口登錄
                    ProcessManager.Ports.Remove(port);
                }

                //取消掉所有接口登錄
                Ports.Clear();

                //通知其他進程接口有變
                List <IOPortedPrc> ListCopy = new List <IOPortedPrc>(ProcessManager.GetCurrentProcesses());

                foreach (IOPortedPrc prc in ListCopy)
                {
                    prc.WriteLine("PortHasChanged");
                }

                ListCopy = null;
            }

            //移除事件監聽
            Engine.OutputDataReceived -= Engine_OutputDataReceived;
            Engine.Exited             -= Engine_Exited;

            //拋棄進程的實體
            Engine.Dispose();
            Engine = null;

            //然後檢查引擎類型, 再從 ProcessManager 相應的名單中除名
            if (ProcessManager.AIPid.Contains(pid))
            {
                ProcessManager.AIPid.Remove(pid);
            }
            if (ProcessManager.InputPid.Contains(pid))
            {
                ProcessManager.InputPid.Remove(pid);
            }
            if (ProcessManager.OutputPid.Contains(pid))
            {
                ProcessManager.OutputPid.Remove(pid);
            }

            //從 ProcessManager 的進程名單中除名
            ProcessManager.RemoveProcess(this);

            //如果是主要引擎的話,嘗試一定次數內重啟
            if (currentType != PortType.Unknown && currentType != PortType.Application)
            {
                if (CrashCount <= 3)
                {
                    ProcessManager.AddProcess(Name, path, "", CrashCount + 1);

                    ActivityLog.Add(Name + Localization.GetMessage("ENGINERESTART", " has exited unexpectedly. Attempting to restart."));
                }
                else
                {
                    Internals.ERROR(Name + Localization.GetMessage("ENGINEEXIT", " has exited unexpectedly. All restart attempts failed."));
                }
            }

            //釋放變量佔用的資源
            Name = null;
            path = null;
            if (RIDs != null)
            {
                RIDs.Clear();
                RIDs = null;
            }

            //最後檢查完備性, 如果不完備的話發出通知
            if (!ProcessManager.CheckCompleteness())
            {
                Internals.ERROR(Localization.GetMessage("ENGINEMISSING", "Some engines are missing. AZUSA will not execute any MUTAN commands unless AI and I/O are all registered."));
            }
        }
예제 #11
0
 public ReturnCode Run()
 {
     //執行 WAITFORRESP 指令, 讓 AZUSA 等待回應然後執行反應
     Internals.Execute("WAITFORRESP", content);
     return(new ReturnCode("", ""));
 }