Hi Guys,

Im having a little trouble with an C# application i'm writing that has plugin. Basically If i add a new plugin (copy it into the plugin folder) with the same name as an existing plugin or if i come across a faulty plugin i want to delete the .dll file.

However it doesn't let me delete the file stating "The File or folder is in use", I assume the application in question is my application and i haven't freed it somehow. Thing is with that though is that if you look at the load plug in function below in the try catch, if its going to fail it often fails on the "Get types" for loop so by the time i get to the catch i assume that pluginAssembly has gone out of scope and therefore i should have no reference? interestingly however I am allowed to move the file and rename it! and i was thinking i could use that as a "mark for deletion" mechanism but it seems hacky. I'm wondering how i can best release this object some kind of Assembly.unload()?? i tried using(Assembly pluginAssembly = Assembly.LoadFrom(filename)) but it protested that Assembly was not derived from IDisposable...which i could have sworn it was!

Any idea whats going on here and what a clean fix would be?

Thanks!, Chris


Adding new Plug:

CleanUpAndClosePlugins();

            //check for directory
            if (!Directory.Exists(PluginDir))
            {
                try
                {
                    Directory.CreateDirectory(PluginDir);
                }
                catch(Exception exept)
                {

                }
            }
         
            
            OpenFileDialog fd = new OpenFileDialog();
            if (fd.ShowDialog() == DialogResult.OK)
            {
                foreach (string filename in fd.FileNames)
                {
                    string newName = PluginDir+"\\" + Path.GetFileNameWithoutExtension(filename) + ".dll";
                 

                        try
                        {
                            File.Move(newName, PluginDir + "\\"  + Path.GetFileNameWithoutExtension(newName) + ".OLD");
                           // File.Delete(newName);

                            File.Copy(filename, newName);  
                        }
                        catch (System.Exception ex)
                        {
                            MessageBox.Show("Unable to overwrite\n " + newName + "\n with \n" + filename + " try closing application and starting again");
                        }                   

                }
            }
            LoadInstalledPluggins();

        }

Load a plug in:

try
            {               

                //Create a new assembly from the plugin file we're adding..
                 Assembly pluginAssembly = Assembly.LoadFrom(FileName);
                

                        if (pluginAssembly == null)
                            return;


                        //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("PluginInterface.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;
                                        newPlugin.pluginType = pluginType;

                                        bool enabled = false;

                                        if (Properties.Settings.Default.EnabledPluginList != null)
                                            enabled = Properties.Settings.Default.EnabledPluginList.Contains(FileName);

                                        //Add the new plugin to our collection here
                                        this.PluginslistBox.Items.Add(newPlugin, enabled);

                                        //cleanup a bit
                                        newPlugin = null;
                                    }

                                    typeInterface = null; //Mr. Clean            
                                }
                            }
                        }
                        
                    pluginAssembly = null; //more cleanup
                }
                catch (System.Exception ex)
                {
[b]                    MessageBox.Show("Invalid plugin in pluggins directory:, will be deleted " + FileName + "\n\nDetails"+ex.Message);[/b]
[b]        //File.Delete(FileName);[/b]
[b]                    File.Move(FileName, PluginDir + "\\" + Path.GetFileNameWithoutExtension(FileName) + ".OLD");[/b]
            
                }         
        
        
           
        }

Think carefully before calling Load, LoadFrom, or LoadFile: these methods permanently load an assembly into the current application domain—even if you do nothing with the resultant Assembly object. Loading an assembly has side effects: it locks the assembly files as well as affecting subsequent type resolution.

The only way to unload an assembly is to unload the whole application domain.

This article has been dead for over six months. Start a new discussion instead.