简体   繁体   English

从AppDomain卸载.DLL所需的帮助 - 即使使用ShadowCopy仍然无法正常工作

[英]Help needed with unloading .DLL's from AppDomain - Still not working even with ShadowCopy

I am trying to do the following. 我正在尝试执行以下操作。 App A is the "mother app". 应用程序A是“母亲应用程序”。 It stays open. 它保持开放。 App B is just a .DLL where I write some classes that are derived from an interface specified in App A. App B只是一个.DLL,我写了一些从App A中指定的接口派生的类。

Then, from App A, I will "import" classes from App B and run methods within them. 然后,从App A,我将从App B“导入”类并在其中运行方法。 I want to be able to dynamically change App B (change code and recompile) and use the new code in App A. 我希望能够动态更改App B(更改代码并重新编译)并使用App A中的新代码。

I have a post-compile command in App B that copies the new .DLL to the App A directory. 我在App B中有一个后编译命令,它将新的.DLL复制到App A目录。 App A creates a new AppDomain and uses ShadowCopying. App A创建一个新的AppDomain并使用ShadowCopying。 I thought this would be sufficient, but when I try to recompile & copy App B's new .DLL, it says that the file is in use and can't be overwritten. 我认为这就足够了,但是当我尝试重新编译和复制App B的新.DLL时,它表示该文件正在使用中且无法覆盖。

Here is the code I have as of now: 这是我现在的代码:

App A (TestServer in code): App A(代码中的TestServer):

namespace TestServer
{
    public interface IRunnable
    {
        void Run();        
    }

    class Program
    {        
        static void Main(string[] args)
        {
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationName = "DemoApp";
            setup.ApplicationBase = Environment.CurrentDirectory;
            setup.ShadowCopyDirectories = Environment.CurrentDirectory;
            setup.ShadowCopyFiles = "true";
            int _domain = 1;

            while (true)
            {
                string typeName = Console.ReadLine();

            AppDomain appDomain = AppDomain.CreateDomain("DemoDomain" + _domain, null, setup);

            IRunnable runner = appDomain.CreateInstanceFromAndUnwrap("TestClient.dll", typeName) as IRunnable;

            runner.Run();

            AppDomain.Unload(appDomain);
            _domain++;
            }
        }   
    }   
}

App B (TestClient in code): App B(代码中的TestClient):

namespace TestClient
{    
    public class TestRunner : TestServer.IRunnable
    {
        public void Run()
        {
            Console.WriteLine("RUNNING");
        }
    }

    public class Bob : TestServer.IRunnable
    {
        public void Run()
        {
            Console.WriteLine("BOB");
        }
    }
}

I have read that if you use stuff from other app domains, those app domains could automatically load the .DLL or something along those lines. 我已经读过,如果您使用来自其他应用程序域的内容,那些应用程序域可以自动加载.DLL或其他内容。 In this case, I fear that using the Interface is causing the base AppDomain to load the .DLL thereby locking it up. 在这种情况下,我担心使用接口会导致基本AppDomain加载.DLL,从而将其锁定。

How can I resolve this issue / is there a better setup?? 我该如何解决这个问题?是否有更好的设置?

NOTE: I have update my code and it still yields the same result. 注意:我已更新我的代码,它仍然产生相同的结果。

Your code still runs in the mother AppDomain, as you're pulling in assemblies and types into there. 您的代码仍然在母AppDomain中运行,因为您将组件和类型拉入其中。 Any code should run in the spawned domain. 任何代码都应该在衍生域中运行。 I've shown one way to set something like that up on my website : A simple way to start your code in a different AppDomain 我已经展示了一种在我的网站上设置类似内容的方法在不同的AppDomain中启动代码的简单方法

I'm not 100% sure on that but that's certainly one step you'll have to undertake 我不是百分百肯定,但这肯定是你必须采取的一步

Update 更新

In terms of the solution presented there, your instantiation of a runner would happen in an inheritor of DomainLifetimeHook. 就那里提出的解决方案而言,运行器的实例化将发生在DomainLifetimeHook的继承者中。 The infrastructure shown ensures that the Start and Stop methods run in the AppDomain created by the class AppDomainExpander. 显示的基础结构确保Start和Stop方法在AppDomainExpander类创建的AppDomain中运行。 That Expander is the class that creates the new domain, hence your domain setup should go in the Create method of the domain. Expander是创建新域的类,因此您的域设置应该在域的Create方法中。

The main problem is where you do: 主要问题是你在哪里:

Type type = assm.GetType("TestClient." + typeName);

This is happening in App A's main AppDomain, and the consequence is that the main AppDomain locks App B's assembly .dll 这发生在App A的主AppDomain中,结果是主AppDomain锁定了App B的程序集.dll

The link in flq's answer to his blog post should work for you. flq对他博客文章的回答中的链接应该适合你。

The type has to be loaded into the main appdomain as soon as you unwrap the ObjectHandle. 只要打开ObjectHandle,就必须将类型加载到主appdomain中。 To work properly, you need to operate on the non-unwrapped ObjectHandle. 要正常工作,您需要对未解包的ObjectHandle进行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM