`

读取Assembly时如何不让DLL锁定

 
阅读更多

在用Assembly.Load 或者Assembly.Loadfrom读取dll时,dll将被锁定,也就是该程序集无法被更新,修改或删除,下面介绍一下如何获取该程序集并使其不被锁定。

(方法一)

首先会创建出两个类,一个Loader一个是RemoteLoader

说明:
1、Loader类提供创建子程序域和卸载程序域的方法;
2、RemoteLoader类提供装载程序集方法;
3、Loader类获得RemoteLoader类的代理对象,并调用RemoteLoader类的方法;
4、RemoteLoader类的方法在子程序域中完成;
5、Loader类和RemoteLoader类均放在AssemblyLoader.dll程序集文件中;

我们再来看代码:
Loader类:

SetRemoteLoaderObject()方法:

  private AppDomain domain = null;
  private Hashtable domains = new Hashtable();  
  private RemoteLoader rl = null;
public RemoteLoader SetRemoteLoaderObject(string dllName)
{
    AppDomainSetup setup 
= new AppDomainSetup();            
    setup.ShadowCopyFiles 
= "true";
    domain 
= AppDomain.CreateDomain(dllName,null,setup);
            
    domains.Add(dllName,domain);    
    
try
    
{
                rl = (AssemblyLoader.RemoteLoader)domain.CreateInstanceFromAndUnwrap(
                "AssemblyLoader.dll","AssemblyLoader.RemoteLoader");         
    }

    
catch
    
{
        
throw new Exception();
    }

}


代码中的变量rl为RemoteLoader类对象,在Loader类中是其私有成员。SetRemoteLoaderObject()方法实际上提供了两个功能,一是创建了子程序域,第二则是获得了RemoteLoader类对象。

请大家一定要注意语句:
rl = (AssemblyLoader.RemoteLoader)domain.CreateInstanceFromAndUnwrap("AssemblyLoader.dll","AssemblyLoader.RemoteLoader");

这条语句就是实现两个程序域之间通讯的关键。因为Loader类是在主程序域中,RemoteLoader类则是在子程序域中。如果我们在Loader类即主程序域中显示实例化RemoteLoader类对象rl,此时调用rl的方法,实际上是在主程序域中调用的。因此,我们必须使用代理的方式,来获得rl对象,这就是CreateInstanceFromAndUnwrap方法的目的。其中参数一为要创建类对象的程序集文件名,参数二则是该类的类型名。

CreateCreateInstanceFromAndUnwrap方法有多个重载。代码中的调用方式是当RemoteLoader类为默认构造函数时的其中一种重载。如果RemoteLoader类的构造函数有参数,则方法应改为:

object[] parms = {dllName};
BindingFlags bindings 
= BindingFlags.CreateInstance |
BindingFlags.Instance 
| BindingFlags.Public;
rl 
= (AssemblyLoader.RemoteLoader)domain.CreateInstanceFromAndUnwrap("AssemblyLoader.dll","AssemblyLoader.RemoteLoader",true,bindings,
null,parms,null,null,null);

详细的调用方式可以参考MSDN。

以下Loader类的Unload方法和LoadAssembly方法():

public Assembly LoadAssembly(string dllName)
{
    
try
    
{
        SetRemoteLoaderObject(dllName);
        
return rl.LoadAssembly(dllName);
    }

    
catch (Exception)
    
{
        
throw new AssemblyLoadFailureException();
    }

}
public void Unload(string dllName)
{
    
if (domains.ContainsKey(dllName))
    
{
        AppDomain appDomain 
= (AppDomain)domains[dllName];
        AppDomain.Unload(appDomain);
        domains.Remove(dllName);
    }
            
}

当我们调用Unload方法时,则程序域domain加载的程序集也将随着而被卸载。LoadAssembly方法中的异常AssemblyLoadFailureException为自定义异常:

    public class AssemblyLoadFailureException:Exception
    
{
        
public AssemblyLoadFailureException():base()
        
{            
        }


        
public override string Message
        
{
            
get
            
{
                
return "Assembly Load Failure";
            }

        }


    }


既然在Loader类获得的RemoteLoader类实例必须通过代理的方式,因此该类对象必须支持被序列化。所以我们可以令该类派生MarshalByRefObject。RemoteLoader类的代码:

    public class RemoteLoader:MarshalByRefObject
    
{
        
public RemoteLoader(string dllName)
        
{
            
if (assembly == null)
            
{
                assembly 
= Assembly.LoadFrom(dllName);
            }

        }
        

        
private Assembly assembly = null;

        
public Assembly LoadAssembly(string dllName)
        
{
            
try
            
{
                assembly 
= Assembly.LoadFrom(dllName);                
                
return assembly;
            }

            
catch (Exception)
            
{
                
throw new AssemblyLoadFailureException();
            }

        }

    }


通过上述的两个类,我们就可以实现程序集的加载和卸载。另外,为了保证应用程序域的对象在内存中被清除,应该令这两个类都实现IDisposable接口,和实现Dispose()方法。

 

在应用时,只需要调用Loader的LoadAssembly方法。

 

(方法二)

只需将该dll 读取到一个字节数组,然后再调用Assembly. Load(),相当于给该dll创建了一个副本。

 

Bye[] content=File.ReadAllBytes(assemblyPath);
Assembly assembly=Assembly.Load(content);
 

 

 

分享到:
评论

相关推荐

    Unity读取Excel需要的工具DLL

    Unity读取Excel时打包成exe会报错,将这些文件放到项目Assets中的Plugins目录下即可解决。文件列表: Excel.dll ICSharpCode.SharpZipLib.dll I18N.CJK.dll I18N.dll I18N.MidEast.dll I18N.Other.dll I18N.Rare.dll...

    C#动态读取DLL

    本篇文章将深入探讨如何在C#中进行DLL的动态读取。 首先,了解DLL的基本概念是必要的。DLL是一种包含可由多个程序同时使用的函数和其他资源的库。它们允许代码重用,减少内存占用,并改善应用程序性能。在C#中,...

    c#csv快速读取类# dll控件

    使用这个DLL时,开发者首先需要将其添加到项目引用中,然后通过`CsvReader`类创建一个实例,设置相应的参数,如分隔符、是否忽略首行(通常为标题行)、如何处理错误等。接着,可以通过`Read()`方法逐行读取数据,...

    三个Excel读取必备Dll文件:Excel.dll 和ICSharpCode.SharpZipLib库文件

    这里提到的“三个Excel读取必备Dll文件”指的是`Excel.dll`和`ICSharpCode.SharpZipLib.dll`,它们可以帮助我们实现这一目标。 首先,`Excel.dll`通常是一个用于读写Excel文件的库,它可能封装了对Microsoft Office...

    C#读取PDF,解析PDF DLL 免费Aspose.Pdf.dll

    有时我们需要在C#应用程序中读取和操作PDF文件,这时可以借助第三方库,比如Aspose.Pdf.dll。 Aspose.Pdf是一款功能强大的PDF处理组件,它为.NET开发者提供了直接操作PDF文件的能力,无需Adobe Acrobat等专业软件。...

    用c#编写的读取大智慧提供的DLL以及每天股票数据

    例如,由于股票数据量可能非常大,读取和处理时应避免一次性加载所有数据,而是采用分批读取或流式处理的方式。此外,必须处理可能出现的错误,如DLL加载失败、函数调用出错或数据解析错误等。 总之,用C#读取大...

    身份证读卡器通用读取信息DLL.rar

    通用读取信息DLL则是这种设备的核心组件,它是一个动态链接库(DLL)文件,提供了与身份证读卡器交互的接口,使得各种应用程序能够方便地调用这些功能来读取和处理身份证信息。 在给定的压缩包"身份证读卡器通用...

    Unity 读取Excel文件 excel.dll

    Unity 读取Excel文件 包含 Excel.dll ICSharpCode.SharpZipLib System.Data

    C# WinForm动态加载DLL通过配置文件

    2. **读取配置文件**:在程序启动时,使用`ConfigurationManager.AppSettings`读取配置文件中的DLL路径。 ```csharp using System.Configuration; string dllPath = ConfigurationManager.AppSettings["DynamicDll...

    PE读取加载DLL

    当我们谈论“PE读取加载DLL”时,我们实际上是在讨论如何在不通过系统API(如LoadLibrary)的情况下,直接使用PE文件格式的内部机制来加载DLL到内存中。 首先,我们需要理解PE文件结构。一个PE文件包含了执行代码、...

    VB调用dll读取身份证信息例子

    在VB(Visual Basic)编程中,有时候我们需要利用外部的dll(动态链接库)文件来扩展功能,例如读取特定硬件设备的数据。在这个例子中,"VB调用dll读取身份证信息"是一个典型的案例,它涉及到如何通过VB程序来操作...

    unity读取excel文件的dll Excel.dll ICSharpCode.SharpZipLib System.Data

    在Unity引擎中,如果你需要处理Excel文件,例如读取数据或进行分析,通常需要借助外部库,因为Unity原生不支持直接操作Excel。本压缩包包含的“Excel.dll”、“ICSharpCode.SharpZipLib”和“System.Data”是实现这...

    C# WinForm 动态加载DLL 通过配置文件

    总结来说,C# WinForm通过配置文件动态加载DLL的关键步骤包括:读取配置文件中的DLL路径,使用`Assembly.LoadFrom`加载DLL,通过反射获取并实例化DLL中的类,最后调用类的方法执行功能。这种方法提高了代码的可维护...

    Unity对Excel的读取所需要的Dll文件

    通过调用该DLL中的方法,可以在不启动Excel程序的情况下读取或写入Excel文件。 - **获取方式**:通常需要从官方渠道获取,例如通过Office开发工具包或者从Microsoft官方网站下载。 2. **ICSharpCode.SharpZipLib....

    PB读取系统版本/读取EXE版本/读取DLL版本

    这有助于确保你的程序所依赖的DLL版本与预期相符,避免版本不兼容导致的问题。 在压缩包中,我们看到有`.pbl`(PowerBuilder库)和`.pbt`(PowerBuilder项目)文件。`.pbl`文件包含源代码、窗口、数据窗口等组件,...

    Unity 读取Excel用的dll文件

    然而,Unity原生并不支持直接读取Excel文件,所以我们需要借助外部的DLL库来实现这一功能。这篇博文(https://editor.csdn.net/md/?articleId=119449823)提供了一个解决方案,即使用特定的DLL文件来读取Excel。 ...

    C#读取HDF5所需dll及示例 WIN64

    同时,由于HDF5文件的特性,读取大文件时需要注意内存管理,避免一次性加载过多数据导致内存溢出。 总的来说,C#结合HDF5 DLL库,为处理大型、复杂的数据提供了强大的工具。通过学习和理解这些API,开发者可以在C#...

    一个读取硬盘序列号与CPU序列号的DLL .rar

    本文章将围绕一个利用VC++6.0开发的DLL(动态链接库)进行深入探讨,该DLL的主要功能是读取硬盘序列号与CPU序列号。考虑到程序的实现细节、应用场景、以及相关的技术要点,我们将会从多个角度进行分析。 首先,DLL...

    unity 读取excel dll

    Unity本身并不直接支持Excel文件的读取,但可以通过引入第三方DLL(动态链接库)来实现这一功能。本篇文章将深入探讨如何在Unity中利用DLL来读取Excel文件。 首先,你需要一个能与Unity兼容的DLL,这通常是通过.NET...

    NXopen二次开发将读取xml文件函数封装为dll方便调用

    8. **错误处理**:在调用DLL函数时,务必做好错误处理,如检查返回值、捕获异常等,以提高程序的健壮性。 通过以上步骤,我们可以将XML文件读取功能封装成DLL,实现代码的重用和模块化。这样的封装不仅简化了主程序...

Global site tag (gtag.js) - Google Analytics