通过AppDomain读取.NET生成的DLL中信息
2005-03-21 16:17
423 查看
对于DLL文件,取出他的Assembly信息可以使用Reflection.Assembly.LoadFrom(Path)语句来实现。但是这样读取之后,如果我们的程序不退出,这个DLL就会被我们的程序进程锁死,不能修改或删除了。为了解决这样的问题,我们通过AppDomain(应用程序域)来实现。
由于我们通过AppDomain来操作,所以我们的信息必须要支持跨应用程序域的访问。为此,我们需要做一个继承自MarshalByRefObject的类来进行我们的核心操作Reflection.Assembly.LoadFrom(Path)。这样在另外一个AppDomain下面我们就可以通过这个类操作Reflection.Assembly.LoadFrom(Path),并且把相关的信息返回回来。具体代码如下。
Private NotInheritable Class AssemblyLoader
Inherits MarshalByRefObject
Private m_Asm As Reflection.Assembly
Public Sub LoadAssemblyFile(ByVal Path As String)
If IO.File.Exists(Path) = True Then
m_Asm = Reflection.Assembly.LoadFrom(Path)
End If
End Sub
End Class
下面我们再做一个类来专门调用这个类,读取DLL文件的Assembly信息。这个类没有什么特别的要求,从Object继承就可以了。然后我们需要一个AppDomain(应用程序域)Private m_ap As AppDomain。
下面我们建立一个函数,它的返回值是我们刚刚建立的那个继承自MarshalByRefObject的类,让我们能够调用Reflection.Assembly.LoadFrom(Path)来读取Assembly信息。
Private Function CreateAssemblyLoaderInstanse(Optional ByVal DomainName As String = "") As AssemblyLoader
Dim objh As System.Runtime.Remoting.ObjectHandle
Dim obj As Object
Dim al As AssemblyLoader
Try
If DomainName.Trim = "" Then
DomainName = DNAME_DEFAULT & Rnd()
End If
AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnResolveEventHandler
m_ap = AppDomain.CreateDomain(DomainName)
objh = m_ap.CreateInstanceFrom(System.Reflection.Assembly.GetExecutingAssembly().Location, GetType(AssemblyLoader).FullName)
obj = objh.Unwrap()
al = CType(obj, AssemblyLoader)
Catch ex As Exception
al = Nothing
End Try
Return al
End Function
前几行代码是为了设定应用程序域的名字的,没有什么特别的。核心的语句是
m_ap = AppDomain.CreateDomain(DomainName)
objh = m_ap.CreateInstanceFrom(System.Reflection.Assembly.GetExecutingAssembly().Location, GetType(AssemblyLoader).FullName)
obj = objh.Unwrap()
al = CType(obj, AssemblyLoader)
首先我们通过AppDomain.CreateDomain(DomainName)建立了自己的AppDomain。然后我们在这个AppDomain下面通过CreateInstanceFrom方法建立AssemblyLoader类的实例。最后通过ObjectHandle.Unwrap方法返回被包装的对象。最后CType成我们的AssemblyLoader。
这样,这个AssemblyLoader就被建立在了一个新的AppDomain里面,而AssemblyLoader的所有操作都是在这个AppDomain中,通过MarshalByRefObject返回给我们主AppDomain。
我们直接调用al.LoadAssemblyFile(Path)就可以读取Assembly信息了。
当我们操作完了这个DLL之后,我们通过AppDomain.Unload(m_ap)卸载这个AppDomain,这样这个DLL的读写LOCK就会解除了。这样就解决了我们的问题。
相关的代码如下。
Private Function OnResolveEventHandler(ByVal sender As Object, ByVal args As ResolveEventArgs) As System.Reflection.Assembly
Dim MyAssembly As System.Reflection.Assembly
If args.Name = System.Reflection.Assembly.GetExecutingAssembly().FullName Then
MyAssembly = System.Reflection.Assembly.LoadFrom(System.Reflection.Assembly.GetExecutingAssembly().Location)
End If
Return MyAssembly
End Function
Private Sub Unload()
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnResolveEventHandler
If Not m_ap Is Nothing Then
AppDomain.Unload(m_ap)
End If
End Sub
但是需要我们注意的是,跨应用程序域的成员通信只支持简单数据类型,或者是从MarshalByRefObject继承的。也就是说,我们通过AssemblyLoader得到的只能是诸如Integer、String这样的东西。所以我们在使用的时候,需要在AssemblyLoader里面做好读取我们需要信息的方法,通过简单数据类型来返回。这也就决定了我们不可能使用这个办法制作出公用性很强的类。
由于我们通过AppDomain来操作,所以我们的信息必须要支持跨应用程序域的访问。为此,我们需要做一个继承自MarshalByRefObject的类来进行我们的核心操作Reflection.Assembly.LoadFrom(Path)。这样在另外一个AppDomain下面我们就可以通过这个类操作Reflection.Assembly.LoadFrom(Path),并且把相关的信息返回回来。具体代码如下。
Private NotInheritable Class AssemblyLoader
Inherits MarshalByRefObject
Private m_Asm As Reflection.Assembly
Public Sub LoadAssemblyFile(ByVal Path As String)
If IO.File.Exists(Path) = True Then
m_Asm = Reflection.Assembly.LoadFrom(Path)
End If
End Sub
End Class
下面我们再做一个类来专门调用这个类,读取DLL文件的Assembly信息。这个类没有什么特别的要求,从Object继承就可以了。然后我们需要一个AppDomain(应用程序域)Private m_ap As AppDomain。
下面我们建立一个函数,它的返回值是我们刚刚建立的那个继承自MarshalByRefObject的类,让我们能够调用Reflection.Assembly.LoadFrom(Path)来读取Assembly信息。
Private Function CreateAssemblyLoaderInstanse(Optional ByVal DomainName As String = "") As AssemblyLoader
Dim objh As System.Runtime.Remoting.ObjectHandle
Dim obj As Object
Dim al As AssemblyLoader
Try
If DomainName.Trim = "" Then
DomainName = DNAME_DEFAULT & Rnd()
End If
AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnResolveEventHandler
m_ap = AppDomain.CreateDomain(DomainName)
objh = m_ap.CreateInstanceFrom(System.Reflection.Assembly.GetExecutingAssembly().Location, GetType(AssemblyLoader).FullName)
obj = objh.Unwrap()
al = CType(obj, AssemblyLoader)
Catch ex As Exception
al = Nothing
End Try
Return al
End Function
前几行代码是为了设定应用程序域的名字的,没有什么特别的。核心的语句是
m_ap = AppDomain.CreateDomain(DomainName)
objh = m_ap.CreateInstanceFrom(System.Reflection.Assembly.GetExecutingAssembly().Location, GetType(AssemblyLoader).FullName)
obj = objh.Unwrap()
al = CType(obj, AssemblyLoader)
首先我们通过AppDomain.CreateDomain(DomainName)建立了自己的AppDomain。然后我们在这个AppDomain下面通过CreateInstanceFrom方法建立AssemblyLoader类的实例。最后通过ObjectHandle.Unwrap方法返回被包装的对象。最后CType成我们的AssemblyLoader。
这样,这个AssemblyLoader就被建立在了一个新的AppDomain里面,而AssemblyLoader的所有操作都是在这个AppDomain中,通过MarshalByRefObject返回给我们主AppDomain。
我们直接调用al.LoadAssemblyFile(Path)就可以读取Assembly信息了。
当我们操作完了这个DLL之后,我们通过AppDomain.Unload(m_ap)卸载这个AppDomain,这样这个DLL的读写LOCK就会解除了。这样就解决了我们的问题。
相关的代码如下。
Private Function OnResolveEventHandler(ByVal sender As Object, ByVal args As ResolveEventArgs) As System.Reflection.Assembly
Dim MyAssembly As System.Reflection.Assembly
If args.Name = System.Reflection.Assembly.GetExecutingAssembly().FullName Then
MyAssembly = System.Reflection.Assembly.LoadFrom(System.Reflection.Assembly.GetExecutingAssembly().Location)
End If
Return MyAssembly
End Function
Private Sub Unload()
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnResolveEventHandler
If Not m_ap Is Nothing Then
AppDomain.Unload(m_ap)
End If
End Sub
但是需要我们注意的是,跨应用程序域的成员通信只支持简单数据类型,或者是从MarshalByRefObject继承的。也就是说,我们通过AssemblyLoader得到的只能是诸如Integer、String这样的东西。所以我们在使用的时候,需要在AssemblyLoader里面做好读取我们需要信息的方法,通过简单数据类型来返回。这也就决定了我们不可能使用这个办法制作出公用性很强的类。
相关文章推荐
- .NET: 通过AppDomain级别控制安全策略的例子
- linux下ADT Bundle实现APP通过jni读取内存信息,以及NDK的使用
- .NET: 如何通过AppDomain动态加载插件程序
- .NET: 通过AppDomain级别控制安全策略的例子
- 通过小练习掌握MFC知识点之起步篇--ComboBox的使用,DLL方式读取文件信息到CListCtrl控件中
- .NET: 如何通过AppDomain动态加载插件程序
- iOS通过app读取通讯录信息(整理)
- ios通过app读取通讯录信息
- 通过小练习掌握MFC知识点之起步篇--ComboBox的使用,DLL方式读取文件信息到CListCtrl控件中
- C#.Net 如何动态加载与卸载程序集(.dll或者.exe)0-------通过应用程序域AppDomain加载和卸载程序集
- log4net, 使用 RemotingAppender 集中管理 跨应用域(App Domain) 的 Log 信息.
- android 通过ApplicationInfo 从androidmanifest 中的application中读取信息。
- 读取MP3 ID3 v1 的 TAG 信息(C# / .Net)
- .net DLL之间是通过AssemblyVersion建立引用关系的
- 微信小程序 解决 “生成 appservice 出错,请查看详细信息” 问题
- SQLite.dll混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。
- 通过应用程序域AppDomain加载和卸载程序集(转自张逸)
- 通过GUID读取COM口信息
- .net 中使用ActiveX控件的自动创建的包装器的问题(自动生成的Interop.Ax*Lib.dll)
- .Net 中使用 ConfigurationSettings 来读取配置信息【转】