在Windows上强制关闭文件的路径

Vas*_*yev 3 c++ winapi temporary-files

我正在为其他开发人员编写临时文件管理器.我想删除文件,即使我们的控制台应用程序崩溃或被"X"按钮关闭.

到目前为止,我找到了std::set_terminate,std::atexit以及SetConsoleCtrlHandler我可以删除我需要的所有临时文件的方法.问题是 - 我无法删除打开的文件.此外 - 我无法控制流到这些文件的流,导致开发人员使用多个库(例如GDAL),这些库使用自己的流机制并且只能接受目标文件路径.

如何强制关闭并删除当前应用程序打开的所有文件?

sno*_*h09 7

您需要关闭当前进程拥有的文件句柄.去做这个:

  • NtQuerySystemInformationAPI与未记录的SystemHandleInformation参数一起使用.
  • 这将为您提供系统中打开的所有句柄的数组
  • 迭代数组并只选择与进程PID匹配的数组,并且是文件句柄
  • 然后,您可以使用GetFinalPathNameByHandle获取已打开文件的路径进一步缩小范围,例如,您可以选择特定文件名或名称中的所有文件tmp.
  • 对于要删除的任何文件,请调用CloseHandle()强制关闭句柄,然后DeleteFile()在路径上调用.

一些代码(没有任何错误检查):

SYSTEM_HANDLE_INFORMATION* pInfo=NULL;
DWORD dwSize=0;
NTSTATUS status=0;

do
{
  // keep reallocing until buffer is big enough
  status = NtQuerySystemInformation(SystemHandleInformation, pInfo, dwSize, &dwSize);
  if (status==STATUS_INFO_LENGTH_MISMATCH)
     pInfo = (SYSTEM_HANDLE_INFORMATION*)realloc(pInfo, dwSize);
} while(status!=0);

// iterate over every handle
for (DWORD i=0; i<pInfo->dwCount; i++)
{
  if (pInfo->handles[i].ProcessID==GetCurrentProcessId() && pInfo->handles[i].HandleType==28)
  {
     TCHAR szPath[MAX_PATH];
     GetFinalPathNameByHandle((HANDLE)pInfo->handles[i].HandleNumber, szPath, MAX_PATH, 0);
     if (_tcsstr(szFilePath, L"filename_I_want_to_delete"))
     {
       CloseHandle((HANDLE)pInfo->handles[i].HandleNumber);
       DeleteFile(szPath);
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

这假设您需要删除的所有文件都由执行删除的进程拥有.如果任何文件属于另一个进程,则需要使用DuplicateHandle()DUPLICATE_CLOSE_SOURCE选项进行额外步骤.假设您具有合适的权限,则会为您提供句柄,然后您可以像以前一样关闭并删除该文件.

有一些很好的示例代码在这里.