Dynamically Updating a Loaded Dll

2

I am creating two solutions for a project I am working on, one for the main server, which will ideally continuously run without need for update. The secondary solution is a DLL, where programmers will continuously change and update code. The server solution is a windows Application and the programmer's solution (the one constantly changing, AKA JupiterCode.dll) is a Class Library.

I am accessing the code via telnet, which is required, and will be entering commands there. The input string will then be executed via reflection on the DLL file ("The user entered 'smile'. Is there a command called 'smile'? Yes, ok, let's execute that code."). I have all of that working and it's going swimmingly, but I hit a snag for when I want to actually update the DLL so that there are more commands the user can enter. When I rebuild the Class Library, the server does not yet reflect the new changes. The server only reflects the new changes when I rebuild the server.

I am trying to have it so when a user enters UPDATE into the telnet server, it will update the loaded DLL with the new DLL, but when I try to do something like...

     string originalDllPath = "C:\\Users\\*****\\Documents\\PseudoGameClient\\bin\\Debug\\JupiterCode.dll";
 string newDllPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\.dll";
 string newDllBakPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeNewBak.dll";
 string oldDllPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCode.dll";
 string oldDllBakPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeBak.dll";

 try
 {
 File.Copy(originalDllPath, newDllPath, true);

 AppDomain.Unload(updatedCodeDomain);
 AppDomain sandbox = AppDomain.CreateDomain("Sandbox");
 Assembly assembly = sandbox.Load(oldDllBakPath);
 upToDateCode = assembly;
 File.Copy(oldDllPath, newDllBakPath, true);
 File.Copy(newDllPath, oldDllPath, true);

 AppDomain.Unload(sandbox);
 AppDomain newCodeDomain = AppDomain.CreateDomain("NewCode");
 assembly = newCodeDomain.Load(oldDllPath);
 upToDateCode = assembly;
 File.Copy(newDllBakPath, oldDllBakPath, true);

 File.Delete(newDllPath);
 File.Delete(newDllBakPath);
 updatedCodeDomain = newCodeDomain;
 }
 catch (Exception ex)
 {
 }

In this method, once it gets to

Assembly assembly = sandbox.Load(oldDllBakPath);

It gives me the exception:

"Could not load file or assembly 'C:\\Users\\aderbedrosia\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeBak.dll' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)":"C:\\Users\\aderbedrosia\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeBak.dll"} System.Exception {System.IO.FileLoadException

(Note: Uptodatecode is kept as a class field because I refer to it later down to execute the commands on it, which again, is working perfectly fine, save for the inability to update.)

I have also tried:

 File.Copy(originalDllPath, newDllPath, true);
 Assembly assembly = Assembly.LoadFrom(oldDllBakPath);
 AppDomain.Unload(updatedCodeDomain);

 AppDomain sandbox = AppDomain.CreateDomain("sandbox");
 sandbox.Load(assembly.GetName());
 upToDateCode = null;
 upToDateCode = assembly;
 File.Copy(oldDllPath, newDllBakPath, true);
 File.Copy(newDllPath, oldDllPath, true);
 assembly = Assembly.LoadFrom(oldDllPath);
 AppDomain.Unload(sandbox);

 AppDomain sandbox2 = AppDomain.CreateDomain("secondarySandbox");
 sandbox2.Load(assembly.GetName());
 upToDateCode = assembly;
 File.Copy(newDllBakPath, oldDllBakPath, true);
 File.Delete(newDllPath);
 File.Delete(newDllBakPath);
 updatedCodeDomain = sandbox2;

and it errors out on

sandbox.Load(assembly.GetName());

with

"Could not load file or assembly 'JupiterCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a98a67e4d0b3db8' or one of its dependencies. The system cannot find the file specified.":"JupiterCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a98a67e4d0b3db8"

Again, to reiterate, I am able to dynamically load the assembly at runtime, but replacing the loaded DLL with a more up to date one (at runtime, without rebuilding) is proving difficult.

c#-4.0
dll
assemblies
appdomain
asked on Stack Overflow Mar 23, 2013 by user2202407

1 Answer

0

For anyone who is facing the same problem, I was able to use a dynamic compiler. look into CSharpCodeProvider and CSharpCodeProvider.CompileAssemblyFromFile. It was everything I needed.

answered on Stack Overflow Mar 24, 2013 by user2202407

User contributions licensed under CC BY-SA 3.0