动态加载C# DLL后如何卸载?相关疑问与场景说明
针对你遇到的DLL加载与卸载问题,结合你做Windows服务动态加载插件的场景,我来逐一解答:
1. 是否需要卸载该DLL?
这完全取决于你的业务需求:
- 如果你的Windows服务需要动态更新DLL(比如不重启服务,直接替换文件夹里的DLL就能生效),那必须卸载,否则DLL会被当前进程锁定,无法替换或删除。
- 如果服务运行期间不需要更新这些DLL,一直用到服务停止,那不需要手动卸载——进程结束时,系统会自动释放所有加载的DLL资源。
2. 如果不卸载,多次调用这段代码会产生什么影响?
你当前的代码是把DLL加载到当前应用域中,.NET的规则是:同一个应用域内,已经加载的DLL无法重复加载,也无法单独卸载。多次调用这段代码的影响主要有:
- 文件锁定:DLL文件会被进程持续占用,你无法替换或删除它,除非停止服务。
- 实例重复创建:每次调用
Activator.CreateInstanceFrom都会创建新的类实例,但DLL本身只会加载一次,不会额外占用更多内存(除非实例没有被GC回收,但这是实例的问题,不是DLL本身)。 - 无法更新:如果后续你替换了文件夹里的DLL,服务依然会使用内存中旧版本的DLL,直到服务重启。
3. 如果需要卸载,该如何操作?
.NET中没有单独卸载单个DLL的机制,只能通过卸载整个应用域来释放该域中加载的所有DLL。所以解决方案是:为每个要加载的DLL创建独立的应用域,用完后卸载这个应用域,就能释放DLL文件。
具体步骤:
第一步:修改你的DLL类
让DLL中的目标类继承MarshalByRefObject(因为跨应用域访问对象需要通过代理,这个类是.NET用于跨域对象访问的基类):
namespace ReportDLL { public class ClassReport : MarshalByRefObject { public string GetReportName() { return "你的报告名称"; } } }
第二步:在服务中用独立应用域加载DLL
替换你原来的代码,改用应用域加载:
string dllPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath.ToString()), "ReportGarage.dll"); string functionName = "GetReportName"; string fullClassName = "ReportDLL.ClassReport"; // 配置新应用域的基础路径(和你的服务程序路径一致) AppDomainSetup domainSetup = new AppDomainSetup(); domainSetup.ApplicationBase = Path.GetDirectoryName(Application.ExecutablePath.ToString()); // 创建独立的应用域(用Guid命名避免重复) AppDomain pluginDomain = AppDomain.CreateDomain($"ReportPluginDomain_{Guid.NewGuid()}", null, domainSetup); try { // 在新应用域中创建DLL实例 ObjectHandle instanceHandle = pluginDomain.CreateInstanceFrom(dllPath, fullClassName); var reportInstance = instanceHandle.Unwrap(); // 调用目标方法 MethodInfo method = reportInstance.GetType().GetMethod(functionName); string reportName = Convert.ToString(method.Invoke(reportInstance, null)); MessageBox.Show(reportName); } finally { // 必须卸载应用域,释放DLL资源 AppDomain.Unload(pluginDomain); }
额外说明:
- 每次加载DLL都创建新的应用域,用完就卸载,这样DLL文件不会被锁定,你可以随时替换文件夹里的DLL,下次服务加载时就是新版本。
- 如果你的方法需要返回复杂对象,要么让对象实现
Serializable接口,要么继承MarshalByRefObject,否则跨应用域传递会出错。 - 对于Windows服务场景,你可以在监控到文件夹有新DLL/更新DLL时,用这个逻辑加载并调用,调用完成后卸载应用域,就能实现动态更新的需求。
内容的提问来源于stack exchange,提问作者GuidoG
相关产品推荐
相关产品推荐

