关闭 LoadLibrary 打开的 DLL 文件句柄

kor*_*123 3 c++ windows dll winapi

如何LoadLibrary在保持库加载的同时关闭通过.dll 调用打开的文件句柄?FreeLibrary例如将不起作用。

就我而言,有一个程序我想保持打开状态,该程序打开了 DLL,但我不想在每次重新编译和替换 DLL 时都关闭该程序。我不在乎程序内存中是否有旧版本的库。DLL 也被另一个程序使用,这就是我希望能够替换它的原因。

Che*_*yDT 7

这是不可能的,因为“加载”的 DLL 是内存映射文件。这意味着“关闭句柄”会将其从内存中删除,因为它不会复制到内存中,而只是被映射

这就是为什么只要所有程序都使用完全相同的文件,DLL 的内存效率就会如此之高——它(几乎)不需要任何额外的内存来加载数百次!(如果您想知道:它被映射为写时复制,因此在内存中修改它不会修改磁盘上的文件,而是将受影响的 4k 页复制到实际内存并在那里修改。)

但是,您可以在文件仍在使用时重命名文件(或移动它,只要它在同一卷上,这在技术上也是重命名操作)。然后你可以用原来的名字创建一个新文件,然后在它被卸载后删除旧文件。

您还可以将旧文件标记为在下次重新启动时自动删除,MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT)但这需要提升权限。非高级更新程序/卸载程序避免这种情况的一个流行选择是将批处理或 vbs 文件放入本地 appdata 文件夹中,该文件夹删除该文件,然后删除它本身(这确实有效,因为脚本复制到内存中)并将其注册在 per - 用户RunOnce注册表项。

(请注意,使用FILE_FLAG_DELETE_ON_CLOSE无法打开文件。)

  • [FreeLibrary](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary) 减少库的引用​​计数。它不一定从调用进程的地址空间卸载模块。这个区别是相当显着的。 (3认同)