zoukankan      html  css  js  c++  java
  • 2018-2-13-C#-动态加载卸载-DLL

    title author date CreateTime categories
    C# 动态加载卸载 DLL
    lindexi
    2018-2-13 17:23:3 +0800
    2018-2-13 17:23:3 +0800
    C#

    我最近做的软件,需要检测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 。

  • 相关阅读:
    容器跨主机网络通信学习笔记(以Flannel为例)
    Kubernetes控制器Job和CronJob
    记一次使用Flannel插件排错历程
    Kubernetes控制器Deployment
    Kubernetes如何通过StatefulSet支持有状态应用?
    react18 来了,我 get 到...
    gojs 实用高级用法
    vuecli3 vue2 保留 webpack 支持 vite 成功实践
    calibre 报错 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 解决
    unable to recognize "*.yaml": no matches for kind "RoleBinding" in version "rbac.authorization.k8s.io/v1beta1"
  • 原文地址:https://www.cnblogs.com/lindexi/p/12086534.html
Copyright © 2011-2022 走看看