简体   繁体   English

动态将c#程序集加载和卸载到appdomain中

[英]dynamically loading and unloading of c# assembly into appdomain

there are many similar questions like this one. 有许多类似的问题。 But they are all years old and dont work (anymore?) today. 但是他们都已经岁了,今天不工作(不再吗?)。

So here is my question: I want to load ac# assembly into memory and find out if it has types included that match an interface i want to use. 所以这是我的问题:我想将ac#程序集加载到内存中,并找出是否包含与我要使用的接口匹配的类型。 If the assembly has this class type included, i reference and use it in my main application. 如果程序集包括此类,我将在我的主应用程序中引用并使用它。 If not, i want to unload the dll and then be able to delete the file (from my main application or by hand while the application is running). 如果不是,我想卸载dll,然后能够删除文件(从我的主应用程序中删除,或者在应用程序运行时手动删除)。

My first implementation simply ommitted the appdomain approach, but it worked (without deleting or replacing assembly files). 我的第一个实现只是省略了appdomain方法,但是它起作用了(无需删除或替换程序集文件)。 Then I tried to load the assemblies as described in various examples. 然后,我尝试按照各种示例中的说明加载程序集。 But with none i was able to delete the not needed assembly files from disk. 但是没有,我能够从磁盘上删除不需要的程序集文件。

Either it is simply not possible to unload and delete assemblies when they were referenced in an application or i am doing something wrong. 在应用程序中引用程序集时,根本无法卸载和删除程序集,或者我做错了什么。 This is what i tried at last: 这是我最后尝试的:

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
using ESTLogViewer_V2.Formulare;
using Parent;
namespace ESTLogViewer_V2
{
    static class Program
    {
        //<summary>
        //Der Haupteinstiegspunkt für die Anwendung.
        //</summary>
        [STAThread]
        static void Main()
        {
            LoadTest.Haupt(null);
        }
    }
}
namespace Parent
{
    public class Constants
    {
        // adjust
        public const string LIB_PATH = @"e:\PRJDOTNET4\ESTLogViewer V2\Plugins\LogFiles_Plugin.dll";
    }

    public interface ILoader
    {
        string Execute();
    }

    public class Loader : MarshalByRefObject, ILoader
    {
        public string Execute()
        {
            var assembly = Assembly.LoadFile(Constants.LIB_PATH);
            foreach (var t in assembly.GetTypes())
            {
                Debug.WriteLine(t.FullName);

            }
            return assembly.FullName;
        }
    }

    class LoadTest
    {
        public static void Haupt(string[] args)
        {
            var domain = AppDomain.CreateDomain("child");
            var loader = (ILoader)domain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
            Console.Out.WriteLine(loader.Execute());
            AppDomain.Unload(domain);
            domain = null;
            File.Delete(Constants.LIB_PATH);
        }
    }
}

So, this code works until the File.Delete statement. 因此,此代码将一直工作到File.Delete语句。 But then it throws an exception: 但随后引发异常:

LogFiles_Plugin.clsSchritLogDateiSplitter
LogFiles_Plugin.clsLogFileMeldDateiSplitter
LogFiles_Plugin.clsLogFileMeldDateiSplitterNG
LogFiles_Plugin.clsAuftragsAnalyseSplitter
LogFiles_Plugin.clsAuftrag
LogFiles_Plugin.clsS_R_SignalSplitter
LogFiles_Plugin.clsLogFileGVMeldDateiSplitter
LogFiles_Plugin.clsLogFileGVTeleSplitter
LogFiles_Plugin.clsLogFileGVTeleSplitter+spalte
<PrivateImplementationDetails>{37CEBF0C-E73A-4FE7-B152-9A858E6C176D}
<PrivateImplementationDetails>{37CEBF0C-E73A-4FE7-B152-9A858E6C176D}+__StaticArrayInitTypeSize=6256
"ESTLogViewer V2.exe" (Verwaltet (v4.0.30319)): "C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll" geladen
Eine Ausnahme (erste Chance) des Typs "System.UnauthorizedAccessException" ist in mscorlib.dll aufgetreten.

Right now, while writing this question, i did some more tests - i tried to find out why i could not delete the assembly file. 现在,在编写此问题时,我进行了更多测试-我试图找出为什么我无法删除程序集文件。 I found out, that it was locked by the visual studio remote debugger. 我发现它已被Visual Studio远程调试器锁定。

So the second question is: How to avoid locking the file with the remote debugger? 因此,第二个问题是:如何避免使用远程调试器锁定文件?

I found that Assembly.LoadFile(...) will lock the file, even beyond the point of unloading the AppDomain. 我发现Assembly.LoadFile(...)将锁定文件,甚至超出卸载AppDomain的程度。

My solution is to first load the assembly bytes into memory, and then load it into the AppDomain: 我的解决方案是先将程序集字节加载到内存中,然后再将其加载到AppDomain中:

var assemblyBytes = System.IO.File.ReadAllBytes("myassembly.dll");
var assembly = System.Reflection.Assembly.Load(assemblyBytes);

That way the file is never locked and you can delete it, etc. 这样,文件就永远不会被锁定,您可以删除它,等等。

There's a better answer to a similar question here . 有更好的回答类似的问题在这里

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

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