Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 关闭LoadLibrary打开的DLL文件句柄_C++_Windows_Winapi_Dll - Fatal编程技术网

C++ 关闭LoadLibrary打开的DLL文件句柄

C++ 关闭LoadLibrary打开的DLL文件句柄,c++,windows,winapi,dll,C++,Windows,Winapi,Dll,如何在加载库的同时关闭由.dll上的LoadLibrary调用打开的文件句柄免费库将不起作用 在我的例子中,有一个程序我想保持打开,该程序的DLL是打开的,但我不想每次重新编译和替换DLL时都关闭该程序。我不在乎程序内存中是否有旧版本的库。DLL也被另一个程序使用,这就是为什么我希望能够替换它。这是不可能的,因为“加载的”DLL是一个内存映射文件。这意味着“关闭句柄”会将其从内存中删除,因为它不会复制到内存中,而只是映射到内存中 这就是为什么只要所有程序都使用完全相同的文件,DLL就具有如此高的

如何在加载库的同时关闭由.dll上的
LoadLibrary
调用打开的文件句柄<例如,代码>免费库将不起作用


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

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

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

但是,您可以在文件仍在使用时重命名该文件(或移动它,只要它位于同一卷上,这在技术上也是一个重命名操作)。然后,您可以使用原始名称创建一个新文件,然后在卸载旧文件后将其删除

您还可以使用
MoveFileEx(MOVEFILE\u DELAY\u UNTIL\u reboot)
将旧文件标记为在下次重新启动时自动删除,但这需要提升权限。非升级更新程序/卸载程序为避免这种情况,通常会在本地appdata文件夹中删除批处理文件或vbs文件,然后删除该文件及其自身(由于脚本复制到内存中,因此可以正常工作),并将其注册到每用户
RunOnce
注册表项中


(请注意,在关闭时使用
file\u FLAG\u DELETE\u打开文件将不起作用。)

有趣的是,在此之前我不知道内存映射文件。谢谢递减库上的引用计数。它不一定从调用进程的地址空间卸载模块。这种区别非常明显,没有要关闭的文件句柄。甚至没有要关闭的节(文件映射)句柄。
HMODULE
是加载模块的基址。在内核调试器中,您可以使用
!vad 1
显示包含控制区域的信息,该区域引用文件对象。在这种情况下,文件对象只有内核指针引用,没有句柄引用。它是通过
FILE\u SHARE\u READ | FILE\u SHARE\u DELETE
共享打开的,这就是它可以重命名的原因,这需要使用
DELETE
访问权限打开文件。在关闭时使用DELETE打开映像映射DLL会失败
NtCreateFile
系统调用,并且
状态无法删除
(不是
状态共享
)因为文件映射为图像。有关检查活动(不可刷新)图像部分的代码示例,请参阅fastfat示例驱动程序中的,该驱动程序调用。