我有几个游戏服务器使用某个 .dll 文件来运行。有时我需要更新游戏服务器,但我不想中断正在运行的游戏。
有没有办法替换 .dll 文件(它被 Windows 锁定),以便使用该文件的游戏服务器的下一个实例打开新版本,而旧版本继续使用该 .dll 的旧版本直到重新启动?
使用其中一种工具来解锁文件并替换它是否安全?
答案1
事实上,你可以通常运行无任何问题(尽管并非总是如此)
您要做的是重命名文件而不移动它(即不更改文件夹结构中的文件位置)并将新文件移动到包含文件夹。
这将使文件句柄保持有效并正常工作,以便预先存在的实例仍然能够正确访问该文件,并且新实例(或新句柄)将转到新文件。
显然,如果程序重新打开同一个 dll 文件并期望它保持完全相同(例如,如果有资源要从 dll 加载,并且对这些资源的引用是从加载 dll 时运行的代码中提取的),这会导致问题,但这绝对不是常态。
答案2
不。即使 DLL可能虽然应用程序运行时 DLL 可以完全映射到物理内存中,但绝对不能保证这一点。DLL 的某些部分(甚至是可执行文件)可以映射到 RAM 中,而其他部分则保留在磁盘上,并可能在以后读入。
当 Windows 将文件的某些部分映射到 RAM 中时,更改磁盘上的文件不会有好结果。Windows 锁定它是有原因的。
编辑:我需要澄清一些事情,因为有些人似乎有意将实际上的应用设计问题,而不是操作系统设计问题。
您可以在不终止进程的情况下更新 Windows 中应用程序使用的 DLL,但应用程序必须以这样的方式编写:可以发出信号卸载程序集,等待更新完成,然后重新加载 DLL。这与您正在运行的操作系统无关。这是一个应用程序设计问题。
编辑:另请参阅Stephane的回答可能的解决方案可能工作,这取决于您的特定应用程序如何响应其 DLL 更改。我认为他值得点赞。
答案3
不,您不应该修改现有的文件句柄。
如果您可以控制程序集的加载,并指定使用 FileShare.Delete 打开它,那么应该可以重命名它。现有进程将继续引用重命名的程序集。
https://stackoverflow.com/questions/7147577/programmatically-rename-open-file-on-windows。
答案4
不,很遗憾,这是不可能的。
抱歉,确切地说,除非有后期绑定,这意味着应用程序在运行该 dll 中的某些部分代码时会使用该 dll,但它仍然不可靠。