C# 动态加载卸载 DLL

我最近做的软件,需要检测dll或exe是否混淆,需要反射获得类名,这时发现,C#可以加载DLL,但不能卸载DLL。于是在网上找到一个方法,可以动态加载DLL,不使用时可以卸载。

我在写一个WPF 程序,发现可以通过 Assembly.Load 加载 DLL,但是如何卸载DLL?下面就来说下如何卸载。

看到 Assembly.Load 是把 DLL 加载到当前程序集,这句话,我就想到了我们的主程序集和当前的不同,那么可以加载到当前不会影响主程序。那么如何新建一个程序集?他是否可以卸载,答案是可以的。

首先,我们可以通过var appDomain = AppDomain.CreateDomain(appDomainName);创建 AppDomain 。他是可以卸载,卸载 AppDomain 使用 AppDomain.Unload ,就可以把加载在 AppDomain 的 DLL 卸载。

于是我们需要把 DLL 加载在 AppDomain ,这样之后可以卸载 AppDomain 动态删掉 加载的DLL。

如果要把 DLL 加载在 AppDomain 需要先写一个类,继承MarshalByRefObject

    internal class ApplicationProxy : MarshalByRefObject
    {
        public void DoSomething()
        {
            
        }
    }

    var proxy =
                appDomain.CreateInstanceAndUnwrap(Assembly.GetAssembly(typeof(ApplicationProxy)).FullName,
                typeof(ApplicationProxy).ToString()) as ApplicationProxy;

我们可以在 DoSomething 函数加载 DLL ,加载的 DLL 在 AppDomain ,不在主程序,所以卸载 AppDomain 可以卸载 DLL

假如是从 文件加载,可以使用 LoadFile

                  var assembly  = Assembly.LoadFile(file.FullName);

assembly 可以获得所有的类和方法。

然后需要卸载时,可以使用 AppDomain.Unload(appDomain);

建议写var assembly = Assembly.LoadFile(file.FullName);在 try,写 AppDomain.Unload(appDomain);在 finally

上面的 appDomainName 是我自己给他的。

http://stackoverflow.com/questions/2132649/loading-unloading-assembly-in-different-appdomain

我们可以验证,如果不使用新建一个 AppDomain 加载的 DLL 会在主程序集,如果使用了,就会在我们新建的 AppDomain 。

首先我们使用 Assembly.LoadFile(file) 加载,再用反射获得当前程序集,然后获取他的所有 type ,当然我们是知道加载的 File 包含的 type,一会可以验证使用已经加载他。

            System.Reflection.Assembly.LoadFile(file);

            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                //查看type               
            }

可以看到 file 包含的 type 在主程序。

我们使用新建 appDomain

              const string appDomainName = "ConfuseChecker";
            var appDomain = AppDomain.CreateDomain(appDomainName);
            var proxy =
                       appDomain.CreateInstanceAndUnwrap(Assembly.GetAssembly(typeof(ApplicationProxy)).FullName,
                           typeof(ApplicationProxy).ToString()) as ApplicationProxy;
            proxy.DoSomething(new FileInfo(file));

            AppDomain.Unload(appDomain);

这时可以看到,我们的主程序没有包含 file 的 type 。


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏木宛城主

Unity应用架构设计(7)——IoC工厂理念先行

一谈到 『IoC』,有经验的程序员马上会联想到控制反转,将创建对象的责任反转给工厂。IoC是依赖注入 『DI』 的核心,大名鼎鼎的Spring框架就是一个非常...

29770
来自专栏尾尾部落

[剑指offer] 用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

10210
来自专栏JavaEE

java基础知识02

1、String字符串: 字符串一旦被初始化,就不可以被改变,存放在方法区中的常量池中。用length()方法获取长度。

9020
来自专栏李航的专栏

Shell 主要逻辑源码级分析:SHELL 运行流程 (1)

分享一下在学校的时候分析shell源码的一些收获,帮助大家了解shell的一个工作流程,从软件设计的角度,看看shell这样一个历史悠久的软件的一些设计优点和缺...

2.2K00
来自专栏我是业余自学C/C++的

汇编语言-第三章 寄存器(栈存储)

38810
来自专栏java技术学习之道

JVM初探 -JVM内存模型

17340
来自专栏上善若水

如何识别C++编译以后的函数名

C/C++语言在编译以后,函数的名字会被编译器修改,改成编译器内部的名字,这个名字会在链接的时候用到。如果用backtrace之类的函数打印堆栈时,显示的就是被...

33720
来自专栏眯眯眼猫头鹰的小树杈

猫头鹰的深夜翻译:理解java的classloader

Java ClassLoader是java运行系统中一个至关重要但是经常被忽略的组件。它负责在运行时寻找并加载类文件。创建自定义的ClassLoader可以彻底...

15240
来自专栏章鱼的慢慢技术路

Go指南练习_Stringer

14420
来自专栏拂晓风起

中文URL编码

21250

扫码关注云+社区

领取腾讯云代金券