using Api.Framework.Events; using Api.Framework.SDK; using Api.Framework.Tools; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; using static System.Net.Mime.MediaTypeNames; using System.Windows.Forms; namespace Api.Framework { /// /// 插件管理 /// public class PluginClient { /// /// 插件集合 /// public static List Plugins { get; private set; } /// /// 插件AES加密 /// private static byte[] Iv, Key; static PluginClient() { Plugins = new List(); Key = new byte[] { 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 }; Iv = new byte[] { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; } /// /// 获取插件新版本 /// /// 需要获取的插件 public static List FindVersion(Plugin plugin) { if (string.IsNullOrEmpty(plugin.VersionXML)) return null; List versions = new List(); Util util = new Util(); var doc = new XmlDocument(); doc.Load(plugin.VersionXML); var nodes = doc.SelectNodes("Version"); foreach (XmlNode item in nodes) { var v = new PluginVersion() { CurMessage = item["CurMessage"].ToString(), CurVersion = Version.Parse(item["CurVersion"].ToString()), SoftVersion = Version.Parse(item["SoftVersion"].ToString()), DownURL = item["DownURL"].ToString() }; versions.Add(v); } versions.OrderByDescending(p => p.CurVersion); return versions; } /// /// 将指定文件的转换成插件,并保存 /// /// 文件路径 /// public static Plugin FileConvertPlugin(string filePath) { if (!File.Exists(filePath)) throw new Exception("文件不存在,请查证。"); if (filePath.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase)) { Util util = new Util(); string fileName = Path.GetFileName(filePath); string path = filePath.Substring(0, filePath.Length - 4); byte[] inputBuffer = util.ReadFile(filePath);// File.ReadAllBytes(filePath); Assembly al = ConvertAssembly(inputBuffer); Plugin p = null; if (al != null) { p = ConvertPlugin(al); if (p == null) throw new Exception("该文件不能不符合插件接口标准!"); // string filep = Path.Combine(Util.MapPath("Plugin"), fileName.Substring(0, fileName.Length - 4) + ".plugin"); string savePath = path + ".plugin"; byte[] bytes = Aes.Create().CreateEncryptor(Key, Iv).TransformFinalBlock(inputBuffer, 0, inputBuffer.Length); File.WriteAllBytes(savePath, bytes); p.CurVersion = al.GetName().Version; p.FilePath = savePath; return p; } else throw new Exception("该文件不能不符合插件接口标准。"); } else if (filePath.EndsWith(".plugin", StringComparison.CurrentCultureIgnoreCase)) { var plugin = GetPlugin(filePath); if (plugin == null) throw new Exception("该文件不能不符合插件接口标准。"); return plugin; } else throw new Exception("该文件不能不符合插件接口标准。"); } /// /// 加载插件 /// /// 重新加载 public static void LodingPlugin(bool reload = false) { EventClient.StopParsing = true; ApiClient.GetSession().Context.Utilities.RemoveCacheAll(); Task.Factory.StartNew(delegate { try { if (reload) { ApiClient.Cache.Cleaner(); lock (Plugins) { foreach (var item in Plugins) { try { item.Stop(); item.Dispose(); } catch (Exception ex) { EventClient.OnEvent(item, $"停止失败{item.Name}:{ex.Message}"); } } Plugins.Clear(); } } string[] plugin_files = Directory.GetFiles(Util.MapPath("Plugin", true), "*.plugin", SearchOption.TopDirectoryOnly); string[] dll_files = Directory.GetFiles(Util.MapPath("Plugin", true), "*.dll", SearchOption.TopDirectoryOnly); List pluginFiles = new List(); pluginFiles.AddRange(plugin_files); pluginFiles.AddRange(dll_files); lock (Plugins) { foreach (var item in pluginFiles) { try { var p = GetPlugin(item); if (p == null) continue; else { #region 显示的插件,不显示的continue了 if (ApiClient.ShowPluginList != null) { if (!p.FilePath.ToLower().Contains("\\main.dll")) { var flag = ApiClient.ShowPluginList.FirstOrDefault(f => p.FilePath.Contains(f)); if (string.IsNullOrWhiteSpace(flag)) { p?.Stop(); continue; } } } #endregion Plugin oldPlugin = Plugins.FirstOrDefault(f => f.GetType().ToString() == p.GetType().ToString()); if (oldPlugin != null)//发现旧插件 { if (oldPlugin.FilePath != item)//可是路径不相同 { EventClient.OnEvent("插件系统", new Events.LogEvents("文件:" + oldPlugin.FilePath + "与" + p.FilePath + "冲突!") { }); } else { if (oldPlugin.Md5 != p.Md5) { Plugins.Remove(oldPlugin); Plugins.Add(p); bool isStart = (oldPlugin.IsRun ? true : false); if (isStart) { oldPlugin.Stop(); oldPlugin.Dispose(); p.Start(); p.IsRun = true; } } //else //{ // if (!p.IsNet) // { // DynnamicDLL dll = p as DynnamicDLL; // if (dll != null) // { // dll.Dispose(); // } // } //} // p.Level = oldPlugin.Level; } } else { p.Level = int.MaxValue; Plugins.Add(p); } } } catch (Exception e) { EventClient.OnEvent(null, new Events.LogEvents("处理文件:" + item + ",发生异常:" + e.Message) { Exception = e }); } } var _plugins = ApiClient.Setting.Plugins; for (int i = 1; i <= _plugins.Count; i++) { Plugin plugin = Plugins.FirstOrDefault(f => f.GetType().ToString() == _plugins[i - 1].ToString()); if (plugin != null) { try { plugin.Level = i; if (!plugin.IsRun) { plugin.Level = i; plugin.Start(); plugin.IsRun = true; } } catch (Exception e) { EventClient.OnEvent(null, new Events.LogEvents(string.Format("启动“{0}”插件失败:{1}", plugin.Name, e.Message)) { Exception = e }); plugin.IsRun = false; } } } Plugins.Sort(); } EventClient.OnEvent(null, MethodType.刷新应用); } catch (Exception ex) { //Console.WriteLine(); } finally { EventClient.StopParsing = false; } }); } /// /// 更新插件 /// /// 版本 /// public static bool UpdatePlugin(PluginVersion version) { return false; } /// /// 添加插件 /// /// 插件路径 /// public static Plugin AddPlugin(string filePath) { try { Plugin p = FileConvertPlugin(filePath); Plugin o = Plugins.FirstOrDefault(f => f.GetType().ToString() == p.GetType().ToString()); if (o != null) { lock (Plugins) { try { if (o.IsRun) { o.Stop(); // o.UnInstall(); o.Dispose(); } p.Level = o.Level; Plugins.Remove(o); Plugins.Add(p); if (o.IsRun) { // p.Install(); p.Start(); p.IsRun = true; } return p; } catch (Exception e) { throw new Exception(string.Format("更新插件“{0}”出错:{1}", p.FilePath, e.Message)); } } } else { lock (Plugins) { Plugins.Add(p); } EventClient.OnEvent(null, MethodType.刷新应用); return p; } } catch (Exception ex) { throw ex; } } /// /// 插件安装 /// /// 要安装的插件对象 public static void Install(Plugin plugin) { string type = plugin.GetType().ToString(); plugin.Start(); plugin.IsRun = true; int level = ApiClient.Setting.Plugins.IndexOf(type); plugin.Level = (level == -1 ? ApiClient.Setting.Plugins.Count : level); if (!ApiClient.Setting.Plugins.Contains(plugin.GetType().ToString())) ApiClient.Setting.Plugins.Add(type); SavePlugin(); } /// /// 插件卸载 /// /// 要卸载的插件对象 public static void UnInstall(Plugin plugin) { if (plugin.IsRun) { try { plugin.IsRun = false; plugin.Level = 1000; plugin.Stop(); plugin.Dispose(); plugin._SDK = null; } catch { } string type = plugin.GetType().ToString(); if (ApiClient.Setting.Plugins.Contains(type)) { ApiClient.Setting.Plugins.Remove(type); SavePlugin(); } } } /// /// 删除插件 /// /// 要删除的插件对象 public static void Delete(Plugin plugin) { try { string type = plugin.GetType().ToString(); lock (Plugins) { UnInstall(plugin); if (Plugins.Contains(plugin)) { Plugins.Remove(plugin); } plugin.Dispose(); if (ApiClient.Setting.Plugins.Contains(type)) { ApiClient.Setting.Plugins.Remove(type); SavePlugin(); } if (File.Exists(plugin.FilePath)) File.Delete(plugin.FilePath); } EventClient.OnEvent(null, MethodType.刷新应用); } catch (Exception) { } } /// /// 保存修通配置 /// private static void SavePlugin() { Util.Save(ApiClient.Setting.Plugins, "系统.插件配置"); } /// /// 调换插件顺序 /// /// 被调换的插件下标 /// 需要调换的插件下标 public static void MovePlugin(int plugin1, int plugin2) { try { var plugin = Plugins[plugin1]; Plugins.Remove(plugin); if (plugin2 > Plugins.Count) Plugins.Insert(Plugins.Count, plugin); else if (plugin2 < 0) Plugins.Insert(0, plugin); else Plugins.Insert(plugin2, plugin); ApiClient.Setting.Plugins.Clear(); int i = 0; foreach (var item in Plugins) { i++; if (item.IsRun) ApiClient.Setting.Plugins.Add(item.GetType().ToString()); } SavePlugin(); } catch (Exception) { } } public static string MovePlugin(Plugin plugin1, Plugin plugin2) { try { if (plugin1 == plugin2) return "插件不能相同!"; if (!Plugins.Contains(plugin1) || !Plugins.Contains(plugin2)) return "插件不存在!"; int level = plugin1.Level; plugin1.Level = plugin2.Level; plugin2.Level = level; int p1 = -1; int p2 = -1; for (int i = 0; i < Plugins.Count; i++) { if (Plugins[i] == plugin1) p1 = i; else if (Plugins[i] == plugin2) p2 = i; if (p1 != -1 && p2 != -1) break; } if (p1 != -1 && p2 != -1) { var temp = Plugins[p1]; Plugins[p1] = Plugins[p2]; Plugins[p2] = temp; Plugins.Sort(); ApiClient.Setting.Plugins.Clear(); foreach (Plugin item in Plugins) { if (item.IsRun) ApiClient.Setting.Plugins.Add(item.GetType().ToString()); } SavePlugin(); return null; } else return "没有找到元素位置!"; } catch (Exception) { } return null; } #region 私有函数 /// /// 寻找一个程序集 /// /// 文件路径 /// private static Assembly FindAssembly(string path) { Util util = new Util(); Assembly assembly = null; try { if (string.IsNullOrWhiteSpace(path) || !System.IO.File.Exists(path)) { return assembly; } if (path.EndsWith(".plugin", StringComparison.CurrentCultureIgnoreCase)) { byte[] inputBuffer = util.ReadFile(path); byte[] mingwen = Aes.Create().CreateDecryptor(Key, Iv).TransformFinalBlock(inputBuffer, 0, inputBuffer.Length); assembly = Assembly.Load(mingwen); } else if (path.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase)) { assembly = Assembly.Load(util.ReadFile(path)); } } catch { } return assembly; } /// /// 通过文件路径获取插件对象 /// /// 文件路径 /// private static Plugin GetPlugin(string filePath) { try { var al = FindAssembly(filePath); if (al != null) { var plugin = ConvertPlugin(al); if (plugin != null) { plugin.FilePath = filePath; plugin.Md5 = (Util.GetFileMd5Code(filePath)); return plugin; } } else { //try //{ // DynnamicDLL dll = ConvertDynnamicDLL(fileName); // if (dll == null) // { // throw new Exception("无法识别动态连DLL!"); // } // if (dll.CheckDLL()) // { // return dll; // } // else // { // throw new Exception("无法正确识别插件信息!"); // } //} //catch (Exception ex) //{ // Client.ClientPro.OnLog("插件系统","转换插件异常:" + ex.Message + "," + fileName); //} } } catch (Exception) { } return null; } /// /// 将字节集转换成 程序集 /// /// /// private static Assembly ConvertAssembly(byte[] body) { try { return Assembly.Load(body); } catch (Exception) { } return null; } /// /// 将程序集转换成Plugin /// /// /// private static Plugin ConvertPlugin(Assembly assembly) { try { if (assembly != null) { foreach (System.Type type in assembly.GetTypes()) { if (type.IsSubclassOf(typeof(Plugin))) { Plugin plugin = (Activator.CreateInstance(type) as Plugin); plugin.CurVersion = assembly.GetName().Version; return plugin; } } } } catch (Exception e) { } return null; } #endregion } }