在运行时加载程序集并调用方法并卸载程序集

Posted

技术标签:

【中文标题】在运行时加载程序集并调用方法并卸载程序集【英文标题】:Load A Assembly in Runtime and call a Method and unload the assembly 【发布时间】:2011-06-25 12:06:30 【问题描述】:

我正在创建一个应用程序,它将连接到几个 sql 数据库并从数据库中获取一些详细信息,

在此应用程序中,我必须加密数据库连接详细信息,例如用户名密码。是的,它非常简单直接,只需编写一个方法来解密凭据。

但在我的情况下,我必须依靠第三方加密机制来解密凭据。此外,我必须连接到几个 sql 服务器,这些服务器将再次使用其他一些加密方法。因此我正在控制我的应用程序以动态加载加密程序集并调用加密方法。

但是当我加载程序集表单 Assembly.LoadFile("Path") 时,我无法卸载加载的程序集。我想我已经在单独的应用程序域中加载了这个程序集,并调用了相关的方法并卸载了该应用程序域。我在这方面需要一些帮助。由于我缺乏知识,我无法调用所需的方法。我的代码如下。请帮助我。

类 ApplicationSettings

    private static ApplicationSettings m_ApplicationSettings;
    public String m_ServerName  get; private set; 
    public String m_DatabaseName  get; private set; 
    public String m_UserID  get; private set; 
    public String m_Password  get; private set; 
    public String m_EncryptionDLLPath get; private set; 
    public String m_NameSpace  get; private set; 
    public String m_ClassName  get; private set; 
    public String m_EncryptionMethodName  get; private set; 
    public String m_DecryptionMethodName  get; private set; 

    private ApplicationSettings()
    
        m_ApplicationSettings = this;
    

    public static ApplicationSettings CurrentValues
    
        get
                        
            return m_ApplicationSettings;
        
        private set
        
            m_ApplicationSettings = value;
        
    

    internal static void Initialize()
    
        CommonFunctions.DataEncryption _enc = new CommonFunctions.DataEncryption();


        ApplicationSettings.CurrentValues = new ApplicationSettings();
        ApplicationSettings.CurrentValues.m_EncryptionDLLPath = @"C:\Users\Administrator\Documents\Visual Studio 2010\Projects\TestApp\TestApp\bin\Debug\AppSec.dll";
        ApplicationSettings.CurrentValues.m_NameSpace = "AppSec";
        ApplicationSettings.CurrentValues.m_ClassName = "AppSecEncDec";
        ApplicationSettings.CurrentValues.m_EncryptionMethodName = "Encrypt";
        ApplicationSettings.CurrentValues.m_DecryptionMethodName = "Decrypt";
        ApplicationSettings.CurrentValues.m_Password = _enc.Decrypt("pzBS3EJDoGM=");
        ApplicationSettings.CurrentValues.m_UserID = "sa";

    




类数据加密

    AppDomain DomainName;        

    //Call the Encryption Method 
    public String Encrypt(Object _DataToEncrypt)
    


    

    //Call the Decryption Method 
    public String Decrypt(Object _DataToDecrypt)
    
        String _Decrypt = "";

        String assemblyFileName = ApplicationSettings.CurrentValues.m_EncryptionDLLPath;
        String assemblyName = ApplicationSettings.CurrentValues.m_NameSpace;

        //Setup the evidence
        Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
        AppDomain TestDomain = AppDomain.CreateDomain(
          "TestDomain", //The friendly name of the domain.
          evidence,   //Evidence mapped through the security policy to establish a top-of-stack permission set.
          AppDomain.CurrentDomain.BaseDirectory,  // The base directory that the assembly resolver uses to probe for assemblies.
          System.IO.Path.GetFullPath(assemblyFileName),    // The path relative to the base directory where the assembly resolver should probe for private assemblies.
          true  // If true, a shadow copy of an assembly is loaded into this application domain.
          );
        string s = TestDomain.Load(assemblyName).FullName;
        string[] myparam = new String[1];
        myparam[0] = "test";


        TestDomain.CreateInstance(TestDomain.Load(assemblyName).GetName().ToString(), ApplicationSettings.CurrentValues.m_NameSpace + "." + ApplicationSettings.CurrentValues.m_ClassName).CreateObjRef(GetType());
        //her i need to execute the Encrypt method which will load form the third party encryption mechanisam

        //method name will be returnd on this parameter in application settings Classes.ApplicationSettings.CurrentValues.m_EncryptionMethodName ;

        UloadAssembly();

        return _Decrypt;
    


    public void UloadAssembly()
    
        //Unload the loaded appdomain
        AppDomain.Unload(DomainName);            
        GC.Collect();
    



提前致谢。

【问题讨论】:

【参考方案1】:

我已经想出了如何做到这一点,并希望它会成功请找到下面的代码,如果用来克服这种情况

       public String Encrypt(Object _DataToEncrypt)
    
        try
        

            String _Encrypt = "";
            LoadAssembly();
            ShowLoadedAssemblies();
            if (ClassInstance != null)
            
                MethodInfo EncryptionMethod = ClassInstance.GetType().GetMethod(Classes.ApplicationSettings.CurrentValues.m_EncryptionMethodName); ;
                if (EncryptionMethod != null)
                
                    object[] myparam = new object[1];
                    myparam[0] = _DataToEncrypt;
                    _Encrypt = (string)EncryptionMethod.Invoke(null, myparam);
                

            

            UloadAssembly();
            ShowLoadedAssemblies();
            return _Encrypt;
        
        catch (Exception ex)
        
            throw new Exception(ex.Message);


        

    

    //Call the Decryption Method 
    public String Decrypt(Object _DataToDecrypt)
    
        String _Decrypt = "";

        LoadAssembly();
        ShowLoadedAssemblies();
        if (ClassInstance != null)
        
            MethodInfo DecryptionMethod = ClassInstance.GetType().GetMethod(Classes.ApplicationSettings.CurrentValues.m_DecryptionMethodName);;
            if (DecryptionMethod != null)
            
                object[] myparam = new object[1];
                myparam[0] = _DataToDecrypt;
                _Decrypt = (string)DecryptionMethod.Invoke(null, myparam);
                           

        
        UloadAssembly();
        ShowLoadedAssemblies();
        return _Decrypt;
    
    //Loading the Assembly 
    public void LoadAssembly()
    




        Evidence evi = new Evidence(AppDomain.CurrentDomain.Evidence);

        DomainName = AppDomain.CreateDomain(Classes.ApplicationSettings.CurrentValues.m_NameSpace
                                            , evi
                                            , AppDomain.CurrentDomain.BaseDirectory
                                            , Classes.ApplicationSettings.CurrentValues.m_EncryptionDLLPath
                                            , true
                                            );

       String LoadingAssemblyName = AssemblyName.GetAssemblyName(Classes.ApplicationSettings.CurrentValues.m_EncryptionDLLPath).FullName;

       ClassInstance = DomainName.CreateInstanceAndUnwrap(LoadingAssemblyName
                                                           , Classes.ApplicationSettings.CurrentValues.m_NameSpace 
                                                              + "." 
                                                              + Classes.ApplicationSettings.CurrentValues.m_ClassName
                                                           );

    
    public void UloadAssembly()
    
        //Unload the loaded appdomain
        AppDomain.Unload(DomainName);            
        GC.Collect();
    

【讨论】:

以上是关于在运行时加载程序集并调用方法并卸载程序集的主要内容,如果未能解决你的问题,请参考以下文章

C#动态加载dll 时程序集的卸载问题

我可以在运行时加载 .NET 程序集并实例化只知道名称的类型吗?

使用 blazor 加载外部 .NET Standard 2.0 程序集

你可以从 C++ 运行 C# 代码吗?

C#高阶-反射

从辅助域调用主应用域中的方法并获取值