Visual Studio中程序运行时如何更新正在使用的DLL文件
运行中不终止进程替换被占用a.dll的实现方法
Windows默认会将加载到进程内存空间的DLL文件加上排他锁,直接执行覆盖、删除操作必然抛出IOException提示文件被占用,以下是经过验证的可行方案,不会触发占用错误:
- 方案1:利用系统重命名规则绕开文件锁
这是最通用、不需要改代码的方案:不要直接对正在占用的a.dll做覆盖、删除操作,先将原文件重命名为同目录下的其他名称(比如a_legacy.dll)——Windows系统允许对已加载的exe、DLL文件执行重命名操作,这一步不会触发占用报错。重命名完成后,原路径就空出来了,直接把新版本的a.dll复制到原路径即可。
注意:已经加载到进程内存里的旧DLL逻辑不会实时替换,新DLL会在下次进程触发该DLL加载动作(比如功能模块重载、应用下次启动)时生效;重命名后的旧DLL文件不要在进程运行期间删除,等应用完全退出后再清理即可。 - 方案2:调整DLL加载逻辑实现热更新
如果是你可掌控代码的自研应用,可以把默认的静态DLL引用改成动态加载模式:- 调用
LoadLibrary加载DLL后,在不需要使用时主动调用FreeLibrary释放DLL对应的句柄,句柄释放后文件锁会自动解除,直接替换DLL文件即可 - 可以搭配独立目录做版本中转:提前把新版DLL放到单独的更新目录,检测到更新时先释放旧DLL的句柄,再从中转目录加载新版DLL,全程主进程不需要退出
- 调用
- 方案3:调用系统原生文件替换API
可以直接调用Windows提供的ReplaceFile接口执行替换操作,该接口原生支持被占用文件的替换逻辑:会先将新文件写入目标位置,把旧文件标记为待回收,等所有引用旧文件的句柄释放后自动完成替换,全程不会抛出占用异常。如果允许重启后生效,也可以调用MoveFileEx接口传入MOVEFILE_DELAY_UNTIL_REBOOT标记,系统会在下次重启时自动完成替换。
注意:不要使用第三方强制解锁工具强行终止进程对DLL的句柄引用,这类操作会直接破坏进程的内存状态,大概率导致应用崩溃、出现无响应等问题。
内容的提问来源于stack exchange,提问作者Vamshi
相关产品推荐
相关产品推荐

