【发布时间】:2009-08-21 11:16:07
【问题描述】:
我正计划编写一个示例程序,用于识别被某个进程锁定/使用的文件(dll 文件)。
我们如何使用 WIN API(一个 C/C++ 函数)以编程方式实现这一点?实际上,当我们执行一些软件升级过程时,其他一些过程可能正在使用库,这将导致升级操作暂时失败。
我想在这里举的最好的例子是 Unlocker 工具,它列出了所有正在使用特定文件的进程/dll。
【问题讨论】:
我正计划编写一个示例程序,用于识别被某个进程锁定/使用的文件(dll 文件)。
我们如何使用 WIN API(一个 C/C++ 函数)以编程方式实现这一点?实际上,当我们执行一些软件升级过程时,其他一些过程可能正在使用库,这将导致升级操作暂时失败。
我想在这里举的最好的例子是 Unlocker 工具,它列出了所有正在使用特定文件的进程/dll。
【问题讨论】:
您可以尝试自己打开文件以进行独占访问。如果任何其他进程打开它们,这应该会失败。
【讨论】:
我认为不编写驱动程序就无法确定进程。幸运的是,Russinovich's Handle tool 包含这样的驱动程序;我建议你运行这个工具。
【讨论】:
如果您不需要知道哪些进程使用了相关文件,您只需使用 CreateFile 打开该文件以进行独占访问。
::CreateFile(filename, 0, 0, 0, OPEN_EXISTING, 0, 0);
【讨论】:
在 Windows 中,文件未“锁定”或“解锁”。如果文件已打开,则打开该文件时指定的共享模式将决定其他打开该文件的尝试是否以及在什么情况下成功。
如果指定了 FILE_SHARE_NONE 标志,则文件被完全锁定,在任何情况下,任何其他打开文件的尝试都不会成功。例如,如果指定了 FILE_SHARE_READ,尝试使用 GENERIC_READ 访问权限打开文件将成功,但 GENERIC_WRITE 将失败。 FILE_SHARE_WRITE 允许打开其他句柄以进行写访问,而 FILE_SHARE_DELETE 相同以进行删除。
一旦您确定了您认为“锁定”的排除级别,您就可以尝试使用相关访问权限打开每个文件,看看它是否因 ERROR_SHARING_VIOLATION 而失败。
【讨论】:
在我看来,Windows API 提供了 EnumProcesses() 来轻松获取活动 processID 的列表,并提供 EnumProcessModules 来获取每个进程的模块句柄列表(如果 EXE 和 DLL 与之关联);最后 GetModuleFileNameEx() 给你加载模块的完整路径和文件名。
因此,您可以轻松地遍历所有加载的 DLL 名称,并且至少在检测到问题时知道哪个进程持有它们 - 并且可能会自动结束该进程。
【讨论】: