现在已经真正找到问题所在,只是探讨一下方法.
问题原型------------
动态加载dll的程序,写在控件上,控件拖到form上即加载dll,读取所有dll提供的服务集合,由用户区选择相应的服务
方便开发.
但是问题是,当重新编译一次以后,就无法加载上次的那个dll,报错误,错误竟然是实现类无法强制转换成其接口!
问题原因------------
实际是这样一个过程.
我的程序代码上表面上看是没有什么问题的,但是编译器有个毛病,就是不管你是否重新编译,它默认
情况下已经动态加载的dll是不会释放的.
这样用dll绑定查看的工具可以看到,执行完毕一次正常程序后,devenv.exe已经把我导入的dll都绑定上去了,
如果再编译肯定没有问题,但是执行的时候,如果再要加载这个dll就报出异常
问题可能的解决方案-----------------
最简单解决方案,在执行编译后执行一次某个*.bat文件,专门删除所有的动态加载的dll.
最理想的解决方案,不管用什么手段,编译完成后,让编译环境自动卸载dll,或者让程序能判断出来程序已经加载了这个dll,不去再次加载
(蓝色的区域并非使用加载后存入某个集合中的方法,因为在此编译那个集合就丢了,肯定要调用windows的某些api去实现)不知道大家看明白了没有!
问题原型------------
动态加载dll的程序,写在控件上,控件拖到form上即加载dll,读取所有dll提供的服务集合,由用户区选择相应的服务
方便开发.
但是问题是,当重新编译一次以后,就无法加载上次的那个dll,报错误,错误竟然是实现类无法强制转换成其接口!
问题原因------------
实际是这样一个过程.
我的程序代码上表面上看是没有什么问题的,但是编译器有个毛病,就是不管你是否重新编译,它默认
情况下已经动态加载的dll是不会释放的.
这样用dll绑定查看的工具可以看到,执行完毕一次正常程序后,devenv.exe已经把我导入的dll都绑定上去了,
如果再编译肯定没有问题,但是执行的时候,如果再要加载这个dll就报出异常
问题可能的解决方案-----------------
最简单解决方案,在执行编译后执行一次某个*.bat文件,专门删除所有的动态加载的dll.
最理想的解决方案,不管用什么手段,编译完成后,让编译环境自动卸载dll,或者让程序能判断出来程序已经加载了这个dll,不去再次加载
(蓝色的区域并非使用加载后存入某个集合中的方法,因为在此编译那个集合就丢了,肯定要调用windows的某些api去实现)不知道大家看明白了没有!
C#中动态加载和卸载DLL
[日期:2009-01-17] 来源:互联网整理 作者:佚名 [字体:大 中 小] 新闻简介: 在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方卸载。在C#中我们也能使用Assembly.LoadFile实现动态加载DLL,但是当你试图卸载时,你会很惊讶的发现Assembly没有提供任何卸载的方法。这是由于托管代码的自动垃圾回收机制会做这件事情,所以C#不提供释放资源
关 键 词:
在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方卸载。在C#中我们也能使用Assembly.LoadFile实现动态加载DLL,但是当你试图卸载时,你会很惊讶的发现Assembly没有提供任何卸载的方法。这是由于托管代码的自动垃圾回收机制会做这件事情,所以C#不提供释放资源的函数,一切由垃圾回收来做。 这引发了一个问题,用Assembly加载的DLL可能只在程序结束的时候才会被释放,这也意味着在程序运行期间无法更新被加载的DLL。而这个功能在某些程序设计时是非常必要的,考虑你正在用反射机制写一个查看DLL中所有函数详细信息的程序,程序提供一个菜单让用户可以选择DLL文件,这时就需要让程序能够卸载DLL,否则一旦用户重新得到新版本DLL时,必须要重新启动程序,重新选择加载DLL文件,这样的设计是用户无法忍受的。 C#也提供了实现动态卸载DLL的方法,通过AppDomain来实现。AppDomain是一个独立执行应用程序的环境,当AppDomain被卸载的时候,在该环境中的所有资源也将被回收。关于AppDomain的详细资料参考MSDN。下面是使用AppDomain实现动态卸载DLL的代码, using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;
namespace UnloadDll
{
class Program
{
static void Main(string[] args)
{
string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName;
Console.WriteLine(callingDomainName);
AppDomain ad = AppDomain.CreateDomain("DLL Unload test");
ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"UnloadDll.exe", "UnloadDll.ProxyObject");
obj.LoadAssembly();
obj.Invoke("TestDll.Class1", "Test", "It's a test");
AppDomain.Unload(ad);
obj = null;
Console.ReadLine();
}
}
class ProxyObject : MarshalByRefObject
{
Assembly assembly = null;
public void LoadAssembly()
{
assembly = Assembly.LoadFile(@"TestDLL.dll");
}
public bool Invoke(string fullClassName, string methodName, params Object[] args)
{
if(assembly == null)
return false;
Type tp = assembly.GetType(fullClassName);
if (tp == null)
return false;
MethodInfo method = tp.GetMethod(methodName);
if (method == null)
return false;
Object obj = Activator.CreateInstance(tp);
method.Invoke(obj, args);
return true;
}
}
} 注意: 1. 要想让一个对象能够穿过AppDomain边界,必须要继承MarshalByRefObject类,否则无法被其他AppDomain使用。 2. 每个线程都有一个默认的AppDomain,可以通过Thread.GetDomain()来得到
后来发现连冰刃都不行.... 普通的批处理肯定也够呛了!
我同事对这个比较明白,正在做个实例,但是告诉我可能结果一样是强制结束编程环境.
我还在等结果 不过这个方案已经做了4天了.....太浪费时间了
已经做到这个程度了,放弃吧又不忍心!
我每次加载前拷贝的另一个子目录下(guid命名的),虽然可能运行会越来越慢,但是GC总会
偶然干一次两次吧 即时不干活,我的程序也可以运行下去,比不能干活强!
试试先
希望大家关注
上面的方法还是不好用啊!
windows编程或者.net编程的原理还是比较难去一下子理解的!