From 31c3939a95cb8f487c83a55179be398af84a4291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mr=2E=E5=96=9C?= <863450594@qq.com> Date: Tue, 9 Jan 2024 13:58:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E4=BC=98=E5=85=88=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Native/PluginManagment.cs | 91 ++++++++++++++----- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/Another-Mirai-Native/Native/PluginManagment.cs b/Another-Mirai-Native/Native/PluginManagment.cs index d7f90b3..e6de0d0 100644 --- a/Another-Mirai-Native/Native/PluginManagment.cs +++ b/Another-Mirai-Native/Native/PluginManagment.cs @@ -25,11 +25,19 @@ namespace Another_Mirai_Native.Native public class PluginManagment { public static PluginManagment Instance { get; set; } + public List Plugins { get; set; } = new(); + public List SavedPlugins { get; set; } = new(); + + public Dictionary PluginEvents { get; set; } = new(); + public Dictionary AppDomains { get; set; } = new(); + public bool Loading { get; set; } = true; + private JObject PluginStatus; + public PluginManagment() { Instance = this; @@ -38,6 +46,7 @@ public PluginManagment() else PluginStatus = new JObject(); } + public List DistinctPluginList() { var pluginList = new List(); @@ -75,6 +84,7 @@ public void Load() LogHelper.WriteLog(LogLevel.Info, "插件载入", $"一共加载了{count}个插件", $"√ {sw.ElapsedMilliseconds} ms"); NotifyIconHelper.AddManageMenu(); } + /// /// 以绝对路径路径载入拥有同名json的dll插件 /// @@ -126,7 +136,7 @@ public bool Load(string filepath) , json["author"].ToString(), json["description"].ToString(), authcode); bool enabled = GetPluginState(appInfo);//获取插件启用状态 //保存至插件列表 - CQPlugin CQPlugin = (CQPlugin)newappDomain.CreateInstanceAndUnwrap(typeof(CQPlugin).Assembly.FullName + CQPlugin plugin = (CQPlugin)newappDomain.CreateInstanceAndUnwrap(typeof(CQPlugin).Assembly.FullName , typeof(CQPlugin).FullName , false , BindingFlags.CreateInstance @@ -134,7 +144,8 @@ public bool Load(string filepath) , new object[] { iLib, appInfo, json.ToString(), dll, enabled, filepath } , null, null); - Plugins.Add(CQPlugin); + Plugins.Add(plugin); + PluginEvents.Add(plugin, json); if (SavedPlugins.Any(x => x.appinfo.Name == appInfo.Name) is false) SavedPlugins.Add(new CQPlugin { appinfo = appInfo, json = json.ToString(), Enable = false, path = filepath }); cq_start(Marshal.StringToHGlobalAnsi(destpath), authcode); @@ -150,7 +161,7 @@ public bool Load(string filepath) /// public void FlipPluginState(CQPlugin CQPlugin) { - string pluginId = CQPlugin.appinfo.Id; + string pluginId = CQPlugin.appinfo.Id; var c = PluginStatus["Status"] .Where(x => x["Name"].ToString() == pluginId) .FirstOrDefault(); @@ -177,6 +188,7 @@ public void FlipPluginState(CQPlugin CQPlugin) } RefreshPluginList(); } + public void RefreshPluginList() { MenuItem menu = NotifyIconHelper.Instance.ContextMenu.MenuItems.Find("PluginMenu", false).First(); @@ -220,20 +232,22 @@ private bool GetPluginState(AppInfo appInfo) .Value() == 1; } } + /// /// 卸载插件,执行被卸载事件,从菜单移除此插件的菜单 /// - /// - public void UnLoad(CQPlugin CQPlugin) + /// + public void UnLoad(CQPlugin plugin) { try { - CQPlugin.dll.CallFunction(FunctionEnums.Disable); + plugin.dll.CallFunction(FunctionEnums.Disable); // CQPlugin.dll.CallFunction(FunctionEnums.Exit); - CQPlugin.dll.UnLoad(); - Plugins.Remove(CQPlugin); - LogHelper.WriteLog(LogLevel.InfoSuccess, "插件卸载", $"插件 {CQPlugin.appinfo.Name} 卸载成功"); - CQPlugin = null; + plugin.dll.UnLoad(); + Plugins.Remove(plugin); + PluginEvents.Remove(plugin); + LogHelper.WriteLog(LogLevel.InfoSuccess, "插件卸载", $"插件 {plugin.appinfo.Name} 卸载成功"); + plugin = null; GC.Collect(); } catch (Exception e) @@ -285,6 +299,7 @@ public void UnLoad() Loading = false; LogHelper.WriteLog("插件卸载完毕"); } + /// /// 成员初始化,用于删除上次运行的临时目录、加载插件以及执行启动事件 /// @@ -298,7 +313,7 @@ public void Init() File.WriteAllText(@"conf\Status.json", PluginStatus.ToString()); } Directory.CreateDirectory("libraries"); - foreach(var item in new DirectoryInfo("libraries").GetFiles()) + foreach (var item in new DirectoryInfo("libraries").GetFiles()) { LogHelper.WriteLog($"载入第三方库: {item.Name}"); Dll.LoadLibrary(item.FullName); @@ -313,34 +328,33 @@ public void Init() LogHelper.WriteLog("插件启动完成,开始处理消息逻辑……"); Loading = false; } + [DllImport("CQP.dll", EntryPoint = "cq_start")] private static extern bool cq_start(IntPtr path, int authcode); + [DllImport("CQP.dll", EntryPoint = "CQ_addLog")] private static extern int CQ_addLog(int authCode, int priority, IntPtr type, IntPtr msg); + /// /// 核心方法调用,将前端处理的数据传递给插件对应事件处理,尝试捕获非托管插件的异常 /// - /// 调用的事件名称,前端统一名称,或许应该写成枚举 + /// 调用的事件名称,前端统一名称,或许应该写成枚举 /// 参数表 [HandleProcessCorruptedStateExceptions] [SecurityCritical] - public CQPlugin CallFunction(FunctionEnums ApiName, params object[] args) + public CQPlugin CallFunction(FunctionEnums function, params object[] args) { - JObject json = new JObject - { - new JProperty("ApiName",JsonConvert.SerializeObject(ApiName)), - new JProperty("Args",JsonConvert.SerializeObject(args)) - }; - if ((ApiName != FunctionEnums.Disable && ApiName != FunctionEnums.Exit && - ApiName != FunctionEnums.Enable && ApiName != FunctionEnums.StartUp) + if ((function != FunctionEnums.Disable && function != FunctionEnums.Exit && + function != FunctionEnums.Enable && function != FunctionEnums.StartUp) && Loading) { LogHelper.WriteLog(LogLevel.Warning, "AMN框架", "插件逻辑处理", "插件模块处理中...", "x 不处理"); return null; } //遍历插件列表,遇到标记消息阻断则跳出 - foreach (var item in Plugins) + foreach (var plugin in SelectPluginsHaveEvent(function).OrderBy(x => x.Item2)) { + var item = plugin.Item1; Dll dll = item.dll; //先看此插件是否已禁用 if (item.Enable is false) continue; @@ -351,7 +365,7 @@ public CQPlugin CallFunction(FunctionEnums ApiName, params object[] args) } try { - int result = dll.CallFunction(ApiName, args); + int result = dll.CallFunction(function, args); //调用函数, 返回 1 表示消息阻塞, 跳出后续 if (result == 1) { @@ -360,15 +374,16 @@ public CQPlugin CallFunction(FunctionEnums ApiName, params object[] args) } catch (Exception e) { - LogHelper.WriteLog(LogLevel.Error, "函数执行异常", $"插件 {item.appinfo.Name} {ApiName} 函数发生错误,错误信息:{e.Message} {e.StackTrace}"); + LogHelper.WriteLog(LogLevel.Error, "函数执行异常", $"插件 {item.appinfo.Name} {function} 函数发生错误,错误信息:{e.Message} {e.StackTrace}"); Thread thread = new(() => { - var b = Error_TaskDialog.ShowErrorDialog($"错误模块:{item.appinfo.Name}\n{ApiName} 函数发生错误\n", $"错误信息:\n{e.Message} {e.StackTrace}"); + var b = Error_TaskDialog.ShowErrorDialog($"错误模块:{item.appinfo.Name}\n{function} 函数发生错误\n", $"错误信息:\n{e.Message} {e.StackTrace}"); switch (b) { case Error_TaskDialog.TaskDialogResult.ReloadApp: ReLoad(); break; + case Error_TaskDialog.TaskDialogResult.Exit: NotifyIconHelper.HideNotifyIcon(); Environment.Exit(0); @@ -381,6 +396,31 @@ public CQPlugin CallFunction(FunctionEnums ApiName, params object[] args) } return null; } + + private List<(CQPlugin, int)> SelectPluginsHaveEvent(FunctionEnums function) + { + List<(CQPlugin, int)> plugins = new(); + foreach (var item in PluginEvents.ToList()) + { + var json = item.Value; + if (json.TryGetValue("event", out var j) + && j != null + && j is JArray events + && events.Any(x => x.ContainsKey("id") && x["id"].Type == JTokenType.Integer + && x.ContainsKey("priority") && x["priority"].Type == JTokenType.Integer + && ((int)x["id"]) == (int)function)) + { + int priority = ((int)events.FirstOrDefault(x => ((int)x["id"]) == (int)function)["priority"]); + plugins.Add((item.Key, priority)); + } + else + { + continue; + } + } + return plugins; + } + /// /// 重载应用 /// @@ -395,6 +435,7 @@ public void ReLoad() LogHelper.WriteLog("插件启动完成,开始处理消息逻辑……"); this.Loading = false; } + public static CQPlugin GetPluginByID(string id) => Instance.Plugins.FirstOrDefault(x => x.appinfo.Id == id); } -} +} \ No newline at end of file