应用程序使用的DLL的热卸载/重新加载

时间:2011-02-03 15:08:15

标签: c#

我有一个加载DLL的应用程序来执行处理的特定部分

Example : "Application.dll" loading "Process.dll" 

Process.dll在运行时动态加载,使用反射,但未在应用程序中引用。

处理完成后,需要在服务器上重新编译DLL并稍后再次加载。
为了做到这一点,我需要释放它,否则我收到以下消息: “无法将文件”Process.dll“复制到”Process.dll“。进程无法访问文件'Process.dll',因为它正由另一个进程使用。”

所以问题是:如何以编程方式从我的应用程序中释放/释放/卸载Process.dll,然后再将其重新加载。当然,重点是 WITHOUT 停止应用程序。

编辑1:

建议的解决方案是这样的:

AppDomain newDomain4Process = AppDomain.CreateDomain("newDomain4Process");
Assembly processLibrary = newDomain4Process.Load("Process.dll");
AppDomain.Unload(newDomain4Process);

我仍然遇到的问题是,虽然我给出了正确的完整路径,但我得到了FileNotFound Exceptionthis post的答案也没有预期效果。

编辑2:

This post救了我的命,这是代码:

class ProxyDomain : MarshalByRefObject
    {
        public Assembly GetAssembly(string AssemblyPath)
        {
            try
            {
                return Assembly.LoadFrom(AssemblyPath);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

   ProxyDomain pd = new ProxyDomain();
   Assembly a = pd.GetAssembly(FullDLLPath);

编辑3:
我没有访问AppDomain并使用之前的解决方案卸载它。 当我使用经典的AppDomain创建方法时,我感觉到阿列克谢的警告:AppDomain.Unload“似乎”工作,但程序集仍然被加载(模块视图)。 所以我仍然以某种方式解决了我的问题,因为我无法真正有效地卸载DLL。

3 个答案:

答案 0 :(得分:17)

自从我查看此内容已经有一段时间,但我很确定您需要创建一个新的AppDomain,然后在其中加载DLL。

原因是您无法自行卸载Assembly,但您可以卸载包含AppDomain的{​​{1}}。

以下是一篇CodeProject文章,介绍了如何执行此操作:To Unload a Running Dll

答案 1 :(得分:6)

将程序集加载到AppDomain后,无法卸载。你必须处置AppDomain。如果需要在应用程序中加载和卸载程序集,则需要生成新的AppDomain并加载程序集,然后在完成程序集后销毁AppDomain

答案 2 :(得分:6)

虽然您似乎根据您的编辑解决了问题,但这里有几条评论:

注意Process.dll“泄漏”到主AppDomain中的对象。即像抛出Process.dll中定义的自定义异常并在主AppDomain中捕获的东西会强制将Process.dll加载到主AppDomain中。执行您感兴趣的操作后,检查主AppDomain中已加载程序集的列表。

卸载AppDomain可能会失败并且可能需要很长时间。