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
}
}