using System; using System.Collections.Generic; using System.Text; using PluginInterfaces; using System.IO; using System.Reflection; using Configuration; using System.Windows.Forms; namespace DotnetCenter { public class PluginServices : IPluginHost { public Attributes ConfigAtributes { get { return ConfigFile.GetInstance(); } } public ILog Log { get { return Center.log; } } /// /// Constructor of the Class /// public PluginServices() { } private Types.AvailablePlugins colAvailablePlugins = new Types.AvailablePlugins(); /// /// A Collection of all Plugins Found and Loaded by the FindPlugins() Method /// public Types.AvailablePlugins AvailablePlugins { get { return colAvailablePlugins; } set { colAvailablePlugins = value; } } /// /// Searches the Application's Startup Directory for Plugins /// public void FindPlugins() { FindPlugins(AppDomain.CurrentDomain.BaseDirectory); } /// /// Searches the passed Path for Plugins /// /// Directory to search for Plugins in public void FindPlugins(string Path) { //First empty the collection, we're reloading them all colAvailablePlugins.Clear(); //Go through all the files in the plugin directory foreach (string fileOn in Directory.GetFiles(Path)) { FileInfo file = new FileInfo(fileOn); //Preliminary check, must be .dll if (file.Extension.Equals(".dll")) { //Add the 'plugin' this.AddPlugin(fileOn); } } } /// /// Unloads and Closes all AvailablePlugins /// public void ClosePlugins() { foreach (Types.AvailablePlugin pluginOn in colAvailablePlugins) { //Close all plugin instances //We call the plugins Dispose sub first incase it has to do //Its own cleanup stuff pluginOn.Instance.Dispose(); //After we give the plugin a chance to tidy up, get rid of it pluginOn.Instance = null; } //Finally, clear our collection of available plugins colAvailablePlugins.Clear(); } public bool ValidatePlugin(string path) { bool result = false; Assembly pluginAssembly = Assembly.LoadFrom(path); //Next we'll loop through all the Types found in the assembly foreach (Type pluginType in pluginAssembly.GetTypes()) { if (pluginType.IsPublic) //Only look at public types { if (!pluginType.IsAbstract) //Only look at non-abstract types { //Gets a type object of the interface we need the plugins to match Type typeInterface = pluginType.GetInterface("PluginInterfaces.IPlugin", true); //Make sure the interface we want to use actually exists if (typeInterface != null) result = true; } } } return result; } /// /// Add a new plugin to our system /// /// /// Return 1 if there is a new plugin, 2 if there aren't errors but we couldn't add any new plugin or 0 if there are some error public int AddPlugin(string FileName) { //Create a new assembly from the plugin file we're adding.. Assembly pluginAssembly = Assembly.LoadFrom(FileName); //Next we'll loop through all the Types found in the assembly foreach (Type pluginType in pluginAssembly.GetTypes()) { if (pluginType.IsPublic) //Only look at public types { if (!pluginType.IsAbstract) //Only look at non-abstract types { //Gets a type object of the interface we need the plugins to match Type typeInterface = pluginType.GetInterface("PluginInterfaces.IPlugin", true); //Make sure the interface we want to use actually exists if (typeInterface != null) { //Create a new available plugin since the type implements the IPlugin interface Types.AvailablePlugin newPlugin = new Types.AvailablePlugin(); //Set the filename where we found it newPlugin.AssemblyPath = FileName; //Create a new instance and store the instance in the collection for later use //We could change this later on to not load an instance.. we have 2 options //1- Make one instance, and use it whenever we need it.. it's always there //2- Don't make an instance, and instead make an instance whenever we use it, then close it //For now we'll just make an instance of all the plugins try { newPlugin.Instance = (IPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); //Set the Plugin's host to this class which inherited IPluginHost newPlugin.Instance.Host = this; //Call the initialization sub of the plugin newPlugin.Instance.Initialize(); //Add the new plugin to our collection here this.colAvailablePlugins.Add(newPlugin); //cleanup a bit newPlugin = null; pluginAssembly = null; //more cleanup return 1; } catch (Exception ex) { Center.log.Write("Error al cargar la dll: " + FileName + " Error: " + ex.Message); pluginAssembly = null; //more cleanup return 0; } } typeInterface = null; //Mr. Clean } } } return 2; } /// /// Remove a existing plugin /// /// /// Return 1 if the plugin has been removed. Return 0 if the plugin hasn't been found and return 2 if the plugin has been found but her assembly doesn't exit (something strange) public int RemovePlugin(string pluginName) { Types.AvailablePlugin plugin = colAvailablePlugins.Find(pluginName); if (plugin != null) { if (File.Exists(plugin.AssemblyPath)) { try { //Center.TreeViewRefenrence.Nodes.Clear(); colAvailablePlugins.Remove(plugin); plugin.Instance.MainInterface.Dispose(); plugin.Instance = null; StreamWriter sw = new StreamWriter(Directories.FilePendingDelete, true); sw.WriteLine(plugin.AssemblyPath); sw.Close(); } catch (Exception ex) { Log.Write(ex.Message); } return 1; } else return 2; } else return 0; } public void DeleteFromPending(string path) { if (File.Exists(Directories.FilePendingDelete)) { StreamReader sr = new StreamReader(Directories.FilePendingDelete); List content = new List(); while (!sr.EndOfStream) content.Add(sr.ReadLine()); sr.Close(); if (content.Contains(path)) { content.Remove(path); StreamWriter sw = new StreamWriter(Directories.FilePendingDelete); foreach (String line in content) sw.WriteLine(line); sw.Close(); } } } public void PendingDelete() { try { if(File.Exists(Directories.FilePluginInterfaces)) File.Delete(Directories.FilePluginInterfaces); if (File.Exists(Directories.FilePendingDelete)) { StreamReader sr = new StreamReader(Directories.FilePendingDelete); List content = new List(); while (!sr.EndOfStream) content.Add(sr.ReadLine()); sr.Close(); foreach (String s in content) { if (File.Exists(s)) File.Delete(s); } File.Delete(Directories.FilePendingDelete); } } catch (Exception ex) { Log.Write(ex.Message); } } } }