/// <summary> /// Unloads a plugin /// </summary> /// <param name="plug">Plugin to unload</param> public void UnloadPlugin(PluginInfo plug) { lock (PluginsLoaded) { PluginsLoaded.ForEach((PluginInfo info) => { if (info.FileName == plug.FileName || info.Plugin == plug.Plugin) { try { info.Plugin.StopPlugin(instance); } catch (Exception ex) { Logger.Log("ERROR in unloading plugin: " + info.Plugin.GetType().Name + " because " + ex, Helpers.LogLevel.Debug, ex); } } }); PluginsLoaded.RemoveAll((PluginInfo info) => { return plug.FileName == info.FileName || info.Plugin == plug.Plugin; }); } }
/// <summary> /// Scans assembly for supported types /// </summary> /// <param name="loadfilename">File name from which assembly was loaded</param> /// <param name="assembly">Assembly to scan for supported types</param> /// <param name="startPlugins">Start plugins found in the assembly after complilation</param> public void LoadAssembly(string loadfilename, Assembly assembly, bool startPlugins) { if (null != PluginsLoaded.Find((PluginInfo info) => { return info.FileName == loadfilename; })) { Logger.Log("Plugin already loaded, skipping: " + loadfilename, Helpers.LogLevel.Info); if (startPlugins) { instance.TabConsole.DisplayNotificationInChat("Plugin already loaded, skipping: " + loadfilename); } return; } foreach (Type type in assembly.GetTypes()) { if (typeof(IRadegastPlugin).IsAssignableFrom(type)) { if (type.IsInterface) continue; try { IRadegastPlugin plug = null; ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(RadegastInstance) }); if (constructorInfo != null) plug = (IRadegastPlugin)constructorInfo.Invoke(new[] { instance }); else { constructorInfo = type.GetConstructor(new Type[] { }); if (constructorInfo != null) plug = (IRadegastPlugin)constructorInfo.Invoke(new object[0]); else { Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + type + " has no usable constructor.", Helpers.LogLevel.Debug); continue; } } PluginInfo info = new PluginInfo() { FileName = loadfilename, Plugin = plug, Started = false }; lock (PluginsLoaded) PluginsLoaded.Add(info); if (startPlugins && plug != null) { try { plug.StartPlugin(instance); info.Started = true; } catch (Exception ex) { Logger.Log(string.Format("Failed starting plugin {0}:", type), Helpers.LogLevel.Error, ex); } } } catch (Exception ex) { Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + ex, Helpers.LogLevel.Debug); } } else { try { instance.CommandsManager.LoadType(type); } catch (Exception ex) { Logger.Log("ERROR in Radegast Plugin: " + loadfilename + " Command: " + type + " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug); } } } }
/// <summary> /// Unloads a plugin /// </summary> /// <param name="plug">Plugin to unload</param> public void UnloadPlugin(PluginInfo plug) { lock (PluginsLoaded) { var pluginInfos = PluginsLoaded.FindAll(info => { return info.Plugin == plug.Plugin; }); foreach (var info in pluginInfos) { AppDomain domain = info.Domain; try { info.Plugin.StopPlugin(instance); } catch (Exception ex) { Logger.Log("ERROR in unloading plugin: " + info.Plugin.GetType().Name + " because " + ex, Helpers.LogLevel.Debug, ex); } PluginsLoaded.Remove(info); if (domain != null && PluginsLoaded.Find(dinfo => { return dinfo.Domain == domain; }) == null) { try { AppDomain.Unload(domain); } catch (Exception ex) { Logger.Log("ERROR unloading application domain for : " + plug.FileName + "\n" + ex.Message, Helpers.LogLevel.Debug); } } } } }
/// <summary> /// Scans assembly for supported types and loads it into it's own domain /// </summary> /// <param name="loadfilename">File name from which assembly was loaded</param> /// <param name="startPlugins">Start plugins found in the assembly after complilation</param> public void LoadAssembly(string loadfilename, Assembly assembly, bool startPlugins) { if (null != PluginsLoaded.Find((PluginInfo info) => { return(info.FileName == loadfilename); })) { Logger.Log("Plugin already loaded, skipping: " + loadfilename, Helpers.LogLevel.Info); if (startPlugins) { instance.TabConsole.DisplayNotificationInChat("Plugin already loaded, skipping: " + loadfilename); } return; } AppDomain domain = null; if (assembly == null) { // Don't load ourselves into a domain if (Path.GetFileName(Assembly.GetEntryAssembly().Location) == Path.GetFileName(loadfilename)) { assembly = Assembly.GetEntryAssembly(); } else { assembly = Assembly.LoadFile(loadfilename); /* Disable creation of domains for now * domain = AppDomain.CreateDomain("Domain for: " + loadfilename); * var loader = (RemoteLoader)domain.CreateInstanceAndUnwrap("Radegast", "Radegast.RemoteLoader"); * assembly = loader.Load(loadfilename); */ } } bool loadedTypesFromAssembly = false; foreach (Type type in assembly.GetTypes()) { if (typeof(IRadegastPlugin).IsAssignableFrom(type)) { if (type.IsInterface) { continue; } try { IRadegastPlugin plug = null; ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(RadegastInstance) }); if (constructorInfo != null) { plug = (IRadegastPlugin)constructorInfo.Invoke(new[] { instance }); } else { constructorInfo = type.GetConstructor(new Type[] { }); if (constructorInfo != null) { plug = (IRadegastPlugin)constructorInfo.Invoke(new object[0]); } else { Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + type + " has no usable constructor.", Helpers.LogLevel.Debug); continue; } } loadedTypesFromAssembly = true; PluginInfo info = new PluginInfo() { FileName = loadfilename, Plugin = plug, Started = false, Domain = domain }; lock (PluginsLoaded) PluginsLoaded.Add(info); if (startPlugins && plug != null) { try { plug.StartPlugin(instance); info.Started = true; } catch (Exception ex) { Logger.Log(string.Format("Failed starting plugin {0}:", type), Helpers.LogLevel.Error, ex); } } } catch (Exception ex) { Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + ex, Helpers.LogLevel.Debug); } } else { try { loadedTypesFromAssembly |= instance.CommandsManager.LoadType(type); loadedTypesFromAssembly |= instance.ContextActionManager.LoadType(type); } catch (Exception ex) { Logger.Log("ERROR in Radegast Plugin: " + loadfilename + " Command: " + type + " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug); } } } if (domain != null && !loadedTypesFromAssembly) { AppDomain.Unload(domain); } }
/// <summary> /// Scans assembly for supported types and loads it into it's own domain /// </summary> /// <param name="loadfilename">File name from which assembly was loaded</param> /// <param name="startPlugins">Start plugins found in the assembly after complilation</param> public void LoadAssembly(string loadfilename, Assembly assembly, bool startPlugins) { if (null != PluginsLoaded.Find((PluginInfo info) => { return info.FileName == loadfilename; })) { Logger.Log("Plugin already loaded, skipping: " + loadfilename, Helpers.LogLevel.Info); if (startPlugins) { instance.TabConsole.DisplayNotificationInChat("Plugin already loaded, skipping: " + loadfilename); } return; } AppDomain domain = null; if (assembly == null) { // Don't load ourselves into a domain if (Path.GetFileName(Assembly.GetEntryAssembly().Location) == Path.GetFileName(loadfilename)) { assembly = Assembly.GetEntryAssembly(); } else { assembly = Assembly.LoadFile(loadfilename); /* Disable creation of domains for now domain = AppDomain.CreateDomain("Domain for: " + loadfilename); var loader = (RemoteLoader)domain.CreateInstanceAndUnwrap("Radegast", "Radegast.RemoteLoader"); assembly = loader.Load(loadfilename); */ } } bool loadedTypesFromAssembly = false; foreach (Type type in assembly.GetTypes()) { if (typeof(IRadegastPlugin).IsAssignableFrom(type)) { if (type.IsInterface) continue; try { IRadegastPlugin plug = null; ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(RadegastInstance) }); if (constructorInfo != null) { plug = (IRadegastPlugin)constructorInfo.Invoke(new[] { instance }); } else { constructorInfo = type.GetConstructor(new Type[] { }); if (constructorInfo != null) { plug = (IRadegastPlugin)constructorInfo.Invoke(new object[0]); } else { Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + type + " has no usable constructor.", Helpers.LogLevel.Debug); continue; } } loadedTypesFromAssembly = true; PluginInfo info = new PluginInfo() { FileName = loadfilename, Plugin = plug, Started = false, Domain = domain }; lock (PluginsLoaded) PluginsLoaded.Add(info); if (startPlugins && plug != null) { try { plug.StartPlugin(instance); info.Started = true; } catch (Exception ex) { Logger.Log(string.Format("Failed starting plugin {0}:", type), Helpers.LogLevel.Error, ex); } } } catch (Exception ex) { Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + ex, Helpers.LogLevel.Debug); } } else { try { loadedTypesFromAssembly |= instance.CommandsManager.LoadType(type); loadedTypesFromAssembly |= instance.ContextActionManager.LoadType(type); } catch (Exception ex) { Logger.Log("ERROR in Radegast Plugin: " + loadfilename + " Command: " + type + " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug); } } } if (domain != null && !loadedTypesFromAssembly) { AppDomain.Unload(domain); } }