c# - Delete dll file after unloading an AppDomain -


i'm trying make game engine, trying replicate piece-by-piece unity functions, loading scripts, have no problem, when have reload them, compilation mono fail, telling me dll accessed, or dll file can't deleted.

here code:

using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.reflection; using system.io; using system.runtime.interopservices; using system.threading; using system.diagnostics; using system.security.policy; using system.security; using system.security.permissions;  public class proxy : marshalbyrefobject {     public assembly getassembly(string assemblypath)     {         try         {             byte[] response = new system.net.webclient().downloaddata(assemblypath);             return assembly.reflectiononlyload(response);         }         catch (exception)         {             return null;         }     }      public assembly getassembly2(string assemblypath, appdomain domain)     {         try         {             byte[] bytesdll = new system.net.webclient().downloaddata(assemblypath);             return domain.load(bytesdll);         }         catch (exception)         {             return null;             // throw new invalidoperationexception(ex);         }     }      public assembly getassemblybyname(assemblyname name, appdomain domain)     {         return domain.reflectiononlygetassemblies().         singleordefault(assembly => assembly.getname() == name);     } }  class program {     public static appdomain domain;     public static assembly assembly;     public static type type;     public static string dllpath;     public static string scriptpath;     public static string classname;     public static string file;     public static dynamic instance;      private static bool compile(string path, out string dir)     {                processstartinfo start = new processstartinfo();         dir = path.getdirectoryname(assembly.getexecutingassembly().location);         dir = path.combine(dir, path.getfilenamewithoutextension(path) + ".dll");          if (file.exists(dir))         {             console.writeline("???????");             file.delete(dir);             console.writeline("???????2");         }          start.filename = path.combine(path.getdirectoryname(assembly.getexecutingassembly().location), "mono\\lib\\mono\\4.5\\mcs.exe");         start.useshellexecute = false;         start.redirectstandarderror = true;         start.redirectstandardoutput = true;         start.arguments = "\"" + path + "\" " + "/target:library" + " " + "/out:" + "\"" + dir + "\""; //+ " " + "/reference:octogonengine.dll" + " /reference:assimpnet.dll";          using (process process = process.start(start))         {             using (streamreader reader = process.standarderror)             {                 string result = reader.readtoend();                 console.writeline(result);             }              using (streamreader reader = process.standardoutput)             {                 string result = reader.readtoend();                 console.writeline(result);             }         }          console.writeline("compilation ok");         return (true);     }      public static void unload()     {         filestream[] streams = null;          if (assembly != null)             streams = assembly.getfiles();          instance = null;         gc.collect();         gc.waitforpendingfinalizers();         gc.collect();         type = null;         assembly = null;         appdomain.unload(domain);         assembly = null;          if (streams != null)         {             (int = 0; < streams.length; i++)             {                 streams[i].dispose();             }         }          gc.collect();         gc.waitforpendingfinalizers();         gc.collect();         directory.delete(cachepath, true);         return;     }      static assembly getassemblybyname(string name, appdomain domain)     {         return domain.getassemblies().                singleordefault(assembly => assembly.getname().name == name);     }      public static string cachepath = "./cache/";      public static void load()     {         directory.createdirectory(cachepath);          if (compile(scriptpath, out program.dllpath))         {             if (file.exists(program.dllpath))             {                 classname = path.getfilenamewithoutextension(program.dllpath);                  appdomainsetup setup = new appdomainsetup();                 setup.applicationbase = appdomain.currentdomain.basedirectory;                 setup.shadowcopyfiles = "true";                 setup.cachepath = cachepath;                 domain = appdomain.createdomain(classname, null, setup);                 domain.docallback(() => appdomain.currentdomain.load(assemblyname.getassemblyname("test.dll")));                 var assemblyloader = (proxy)domain.createinstanceandunwrap(typeof(proxy).assembly.fullname, typeof(proxy).fullname);                 assembly = assemblyloader.getassembly(program.dllpath);                  /*if (assembly == null)                 {                     console.writeline("damn");                 }*/                  if (assembly != null)                 {                     type = assembly.gettype(classname);                 }                  if (file.exists(scriptpath))                     program.file = file.readalltext(scriptpath);             }         }     }      static bool check = false;      static void appdomaininit(string[] args)     {         if (!file.exists(args[0]))         {             return;         }     }      public static void init(string scriptpath)     {         if (file.exists(scriptpath))         {             program.file = file.readalltext(scriptpath);             program.scriptpath = scriptpath;             program.load();         }     }      static void main(string[] args)     {         program.init(path.combine(path.getdirectoryname(assembly.getexecutingassembly().location), "test.cs"));         program.unload();         //here crash :/         file.delete(program.dllpath);         console.writeline("???");     } } 

(to test, may need copy mono in executing directory, wich can found @ : http://www.mono-project.com/download/)

does have clue on can either, force delete dll file, or make file accessible deletion?

if not, have clue on way unity load , reload scripts, how make way?

so crafted example works fine me

project consoleapplication1.exe

using system; using system.collections.generic; using system.io; using system.linq; using system.reflection; using system.text; using system.threading.tasks;  namespace consoleapplication1 {     class program     {         static void main(string[] args)         {             try             {                 string pathtoassembly = args[0];                 appdomain dom = appdomain.createdomain("some");                 assemblyname assemblyname = new assemblyname();                 assemblyname.codebase = "loader.dll";                 dom.load(assemblyname);                 object loader = dom.createinstanceandunwrap("loader", "loader.asmloader");                 type loadertype = loader.gettype();                 loadertype.getmethod("loadassembly").invoke(loader, new object[] { pathtoassembly });                                 //make sure given assembly not loaded in main app domain , locked                 appdomain.currentdomain.getassemblies().all(a => { console.writeline(a.fullname); return true; });                 appdomain.unload(dom);                 gc.collect();                 gc.waitforpendingfinalizers();                 gc.collect();                 file.delete(pathtoassembly);             }             catch(exception ex)             {                 console.writeline(ex.tostring());             }         }     } } 

class library loader.dll:

using system; using system.collections.generic; using system.linq; using system.reflection; using system.text; using system.threading.tasks;  namespace loader {     public class asmloader: marshalbyrefobject     {         public asmloader()         {         }          public void loadassembly(string path)         {             assemblyname n = new assemblyname();             n.codebase = path;             appdomain.currentdomain.load(n);         }     } } 

class library testasm.dll

... whatever code.... 

put 3 files in same folder, open cmd line in folder , issue command:

consoleapplication1.exe testasm.dll 

it load loader.dll main app domain , remote appdomain create marshalled proxy asmloader object, load testasm.dll remote domain via marshalled asmloader.loadassembly invocation. consoleapplication1.exe outputs assemblies loaded in current appdomain console see testasm.dll not loaded in it. unloads remote appdomain, deletes testasm.dll fine.


Comments

Popular posts from this blog

Email notification in google apps script -

c++ - Difference between pre and post decrement in recursive function argument -

javascript - IE11 incompatibility with jQuery's 'readonly'? -