c++ WinAPI 获取文件被占用的进程信息
如题
比如我们删除某个文件中,如果文件被占用的话是删除不掉的,那么替换操作啥都不行

故要实现这个提前检测有哪些被占用了, 已经被哪个进程占用的.
我这个需求就是检测dll被哪个进程占用的
总结了3种解决方案
1. 通过拍进程快照,然后遍历每个进程上面dll module, 然后dll 名字匹配的形式.
这里引发了一个问题, 我这个进程是32位的,然后我的dll 有64 和32位的, 拍进程快照的方式
32位进程 只能读32位进程的dll模块信息

当遍历的目标进程是64位时 会lasterror 为299 我看了一下,是进程位数不匹配.
然后我看了一下 procexp_Chn.exe 这个工具我打开的是32位的 为啥电脑上的32和64位的进程模块信息都能
加载出来呢?? 我仔细看了一下 原来你打开32位的进程,它会启动个64位的后台进程把相关信息传递给32位的进程.
这是我打开的

这是它自己开的

行了 这个方案不行.
第二种方案 通过 命令行 tasklist /m dllName
这个 /m 参数就是找这个dll 被哪个进程占用了

这个简单啊, 但是遇到个很奇怪奇怪的问题
我通过winapi 管道的形式, QProcess 的形式,打开 cmd 执行这个命令行都会获取不到结果, system("")
也不行,会阻塞死控制台
试了很多种 都不行, 感觉不是代码层面的问题了, 别人用我的代码都能正常执行, 在我机器会出问题 卡住
我ping baidu 啥的都可以 tasklist 也可,唯独加 /m 参数出问题
折腾一下午 还是不行,要抑郁了 又找了新方案
第三种方案
看的这个 MSDN 上的 How do I find out which process has a file open?
链接如下
https://devblogs.microsoft.com/oldnewthing/?p=8283
然后改了一下 发现很好使, 代码贴一下.
#include <windows.h>
#include <RestartManager.h>
#include <stdio.h>
#pragma comment(lib, "Rstrtmgr.lib")
int test()
{
DWORD dwSession = 0;
WCHAR szSessionKey[CCH_RM_SESSION_KEY + 1];
DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey);
if (dwError != ERROR_SUCCESS)
{
wprintf(L"RmStartSession Start Error, ErrorCode: %d\n", dwError);
getchar();
}
//你的dll 绝对路径
PCWSTR pszFile = L"C:/Users/info/AppData/Local/xxx/SWVirtualCam_x64.dll";
dwError = RmRegisterResources(dwSession, 1, &pszFile, 0, NULL, 0, NULL);
if (dwError != ERROR_SUCCESS)
{
wprintf(L"RmRegisterResources for File %ls Error, ErrorCode: %d\n", pszFile, dwError);
getchar();
}
DWORD dwReason = 0;
UINT i = 0;
UINT nProcInfoNeeded = 0;
UINT nProcInfo = 10;
RM_PROCESS_INFO rgpi[10];
memset(rgpi, 0, sizeof(rgpi));
dwError = RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, rgpi, &dwReason);
if (dwError != ERROR_SUCCESS)
{
wprintf(L"RmGetList Error, ErrorCode: %d\n", dwError);
getchar();
}
if (nProcInfoNeeded == 0)
{
wprintf(L"This file is not in locked!");
getchar();
}
for (i = 0; i < nProcInfo; i++)
{
wprintf(L"The locked file: %ls\n\n", pszFile);
wprintf(L"Who lock this file:\n");
wprintf(L"Name: \t%ls\n", rgpi[i].strAppName);
wprintf(L"ID : \t%d\n", rgpi[i].Process.dwProcessId);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, rgpi[i].Process.dwProcessId);
if (hProcess)
{
// 这个if语句是为了判断是否是某个程序的某个进程(因为一个程序可以有多个进程)
FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)
&& CompareFileTime(&rgpi[i].Process.ProcessStartTime, &ftCreate) == 0)
{
WCHAR sz[MAX_PATH] = { 0 };
DWORD ProcPathMaxLength = MAX_PATH;
if (QueryFullProcessImageNameW(hProcess, 0, sz, &ProcPathMaxLength) && ProcPathMaxLength <= MAX_PATH)
{
wprintf(L"Path: \t%ls\n", sz);
}
}
wprintf(L"\n");
CloseHandle(hProcess);
}
}
RmEndSession(dwSession);
getchar();
return 0;
}
这个demo 代码检测没有问题, 原理就是通过 windows 的重启管理器的 文件引用计数来的
基于demo代码 封装改一下,就满足需求了
更多推荐
所有评论(0)