如何从文件名中找到哪个进程对文件有句柄

Posted

技术标签:

【中文标题】如何从文件名中找到哪个进程对文件有句柄【英文标题】:how to find which process has a handle on a file from the file name 【发布时间】:2021-06-30 05:33:24 【问题描述】:

Windows c++ API 中是否有任何内容可以为我提供具有给定文件句柄的进程列表?

【问题讨论】:

到目前为止,您在文档中的研究揭示了什么? 在 linux 中有 fuser 用于此。显然,windows 等价物称为 Handle(仅通过灼热的 windows fuser 找到)。这是一个命令而不是 api 调用,但可能有助于您的搜索 我现在唯一的想法是使用文件名调用handle.exe,这将为我提供详细信息。如果存在执行此操作的现有 api,我不想为此启动一个过程。 @sriram 我对 Windows 了解不多,但在 unix 中,如果我想知道 fuser 正在使用什么系统调用,我会使用 strace 来查看发生的系统调用。显然windows有一个等效的进程监视器:technet.microsoft.com/en-us/sysinternals/bb896645.aspx我会在handle.exe上试试看它在做什么 【参考方案1】:

来自微软的博客:How do I find out which process has a file open?

输入Restart Manager。

重新启动管理器的官方目标是帮助关闭和重新启动正在使用您要更新的文件的应用程序。为了做到这一点,它需要跟踪哪些进程持有对哪些文件的引用。正是这里使用的数据库。 (为什么内核会跟踪哪些进程打开了文件?因为这与不跟踪您不需要的信息的原则相反:现在它需要信息!)

这是一个简单的程序,它在命令行上获取文件名并显示哪些进程打开了文件。

#include <windows.h>
#include <RestartManager.h>
#include <stdio.h>

int __cdecl wmain(int argc, WCHAR **argv)

 DWORD dwSession;
 WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] =  0 ;
 DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey);
 wprintf(L"RmStartSession returned %d\n", dwError);
 if (dwError == ERROR_SUCCESS) 
   PCWSTR pszFile = argv[1];
   dwError = RmRegisterResources(dwSession, 1, &pszFile,
                                 0, NULL, 0, NULL);
   wprintf(L"RmRegisterResources(%ls) returned %d\n",
           pszFile, dwError);
  if (dwError == ERROR_SUCCESS) 
   DWORD dwReason;
   UINT i;
   UINT nProcInfoNeeded;
   UINT nProcInfo = 10;
   RM_PROCESS_INFO rgpi[10];
   dwError = RmGetList(dwSession, &nProcInfoNeeded,
                       &nProcInfo, rgpi, &dwReason);
   wprintf(L"RmGetList returned %d\n", dwError);
   if (dwError == ERROR_SUCCESS) 
    wprintf(L"RmGetList returned %d infos (%d needed)\n",
            nProcInfo, nProcInfoNeeded);
    for (i = 0; i < nProcInfo; i++) 
     wprintf(L"%d.ApplicationType = %d\n", i,
                              rgpi[i].ApplicationType);
     wprintf(L"%d.strAppName = %ls\n", i,
                              rgpi[i].strAppName);
     wprintf(L"%d.Process.dwProcessId = %d\n", i,
                              rgpi[i].Process.dwProcessId);
     HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
                                   FALSE, rgpi[i].Process.dwProcessId);
     if (hProcess) 
      FILETIME ftCreate, ftExit, ftKernel, ftUser;
      if (GetProcessTimes(hProcess, &ftCreate, &ftExit,
                          &ftKernel, &ftUser) &&
          CompareFileTime(&rgpi[i].Process.ProcessStartTime,
                          &ftCreate) == 0) 
       WCHAR sz[MAX_PATH];
       DWORD cch = MAX_PATH;
       if (QueryFullProcessImageNameW(hProcess, 0, sz, &cch) &&
           cch <= MAX_PATH) 
        wprintf(L"  = %ls\n", sz);
       
      
      CloseHandle(hProcess);
     
    
   
  
  RmEndSession(dwSession);
 
 return 0;

【讨论】:

请注意,重启管理器需要与 Rstrtmgr.lib 链接【参考方案2】:

http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx?fid=422864&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=2277170

这篇文章解释得很好。 它使用 NtQuerySystemInformation 来获取句柄。

http://msdn.microsoft.com/en-us/library/ms724509(VS.85).aspx

【讨论】:

以上是关于如何从文件名中找到哪个进程对文件有句柄的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中按进程获取打开文件句柄的列表?

Perl - Win32 - 如何从另一个进程非阻塞读取文件句柄?

Linux中如何解除最大进程数和最大文件句柄打开数限制?

检查文件是不是被进程文件句柄锁定

文件句柄

如何查看某进程调用的DLL文件?