动态更新已加载的Dll

时间:2013-03-23 15:00:48

标签: c#-4.0 dll assemblies appdomain

我正在为我正在处理的项目创建两个解决方案,一个用于主服务器,理想情况下,无需更新即可连续运行。辅助解决方案是DLL,程序员将不断更改和更新代码。服务器解决方案是一个Windows应用程序,程序员的解决方案(不断变化的,AKA JupiterCode.dll)是一个类库。

我通过telnet访问代码,这是必需的,并将在那里输入命令。然后输入字符串将通过DLL文件上的反射执行(“用户输入'微笑'。是否有一个名为'smile'的命令?是的,好的,让我们执行该代码。”)。我已经完成了所有工作并且它正在游泳,但是当我想要实际更新DLL以便用户可以输入更多命令时,我遇到了麻烦。当我重建类库时,服务器尚未反映新的更改。服务器仅在重建服务器时反映新的更改。

我试图这样做当用户将UPDATE输入到telnet服务器时,它将使用新的DLL更新加载的DLL,但当我尝试做类似的事情时......

     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)
 {
 }

在这种方法中,一旦到达

Assembly assembly = sandbox.Load(oldDllBakPath);

它给了我例外:

  

“无法加载文件或程序集”C:\\ Users \\ aderbedrosia \\ Documents \\ PseudoServerStub \\ bin \\ Debug \\ JupiterCodeBak.dll'或其依赖项之一。给定的程序集名称或代码库是无效。(HRESULT异常:0x80131047)“:”C:\\ Users \\ aderbedrosia \\ Documents \\ PseudoServerStub \\ bin \\ Debug \\ JupiterCodeBak.dll“} System.Exception {System.IO.FileLoadException

(注意:Uptodatecode作为一个类字段保存,因为我稍后会引用它来执行它上面的命令,除了无法更新外,它再次正常工作。)

我也尝试过:

 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;

并且错误输出

sandbox.Load(assembly.GetName());

  

“无法加载文件或程序集”JupiterCode,Version = 1.0.0.0,   Culture = neutral,PublicKeyToken = 9a98a67e4d0b3db8'或其中一个   依赖。系统找不到该文件   指定。“:”JupiterCode,Version = 1.0.0.0,Culture = neutral,   公钥= 9a98a67e4d0b3db8"

同样,重申一下,我能够在运行时动态加载程序集,但是用更新的程序替换加载的DLL(在运行时,没有重建)是很困难的。

1 个答案:

答案 0 :(得分:0)

对于遇到同样问题的人,我能够使用动态编译器。查看CSharpCodeProvider和CSharpCodeProvider.CompileAssemblyFromFile。这就是我需要的一切。