技术好文:VisualC++查看文件被哪个进程占用

简介: 技术好文:VisualC++查看文件被哪个进程占用

参考于:


有别于我之前写的文章,这个方法对DLL貌似并不适用,猜测Windows上dll并不算是文件句柄,没办法被NtQuerySystemInformation识别到


之前的文章:


底下是使用方法:


查看文件是否其他进程占用


METHOD:


主要使用BOOL FindFileHandle(LPCTSTR lpName, vector& handles); 底下定义tstring类似于wstring,说实在我对这块不清楚,可能为了配合WINAPI才define这个数据类型,毕竟底下很多API和数据类型和枚举变量都被Windows藏起来了


PARAMETER:


LPCTSTR lpName:输入值,文件的完整地址


vector& handles:输出值,存储着占用文件的进程详细信息的容器


RETURN:


成功为1,失败为0


WARNING:


函数要遍历所有文件句柄,找出与文件路径匹配的文件句柄,并通过文件句柄找到占用他的进程句柄,所以耗时很久,常规要一秒到两秒左右,谨慎使用


#include "stdafx.h"


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include [span style=//代码效果参考:http://www.lyjsj.net.cn/wz/art_23801.html

"color: rgba(0, 0, 255, 1)">string

#include


#include


#pragma comment(lib, "psapi.lib")


#pragma comment(lib, "shlwapi")


using namespace std;


typedef std::basic_string

#ifndef _countof


#define _countof(array) (sizeof(array)/sizeof((array)【0】))


#endif


EXTERN_C BOOL GetFilePathFromHandleW(HANDLE hFile, LPWSTR lpszPath, UINT cchMax);


EXTERN_C BOOL GetFilePathFromHandleA(HANDLE hFile, LPSTR lpszPath, UINT cchMax);


#ifdef UNICODE


#define GetFilePathFromHandle GetFilePathFromHandleW


#else


#define GetFilePathFromHandle GetFilePathFromHandleA


#endif


#define NT_SUCCESS(status) (status == (NTSTATUS)0x00000000L)


#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)


#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)


#define SystemHandleInformation ((SYSTEM_INFORMATION_CLASS)16)


// NTQUERYOBJECT


typedef struct _OBJECT_NAME_INFORMATION {


UNICODE_STRING Name;


WCHAR NameBuffer【1】;


} OBJECT_NAME_INFORMATION, POBJECT_NAME_INFORMATION;


//winternl.h中以定义,微软未放出134的定义,需自己手动定义


typedef enum _OBJECT_INFORMATION_CLASS_SELFDEFINE {


//ObjectBasicInformation,


ObjectNameInformation=1,


//ObjectTypeInformation,


ObjectAllInformation=3,


ObjectDataInformation=4


} OBJECT_INFORMATION_CLASS_SELFDEFINE, POBJECT_INFORMATION_CLASS_SELFDEFINE;


typedef NTSTATUS(WINAPI NTQUERYOBJECT)(


_Inopt HANDLE Handle,


In OBJECT_INFORMATION_CLASS_SELFDEFINE ObjectInformationClass,


_Outopt PVOID ObjectInformation,


In ULONG ObjectInformationLength,


_Outopt PULONG ReturnLength);


// NTQUERYSYSTEMINFORMATION


typedef struct _SYSTEM_HANDLE {


DWORD dwProcessId;


BYTE bObjectType;


BYTE bFlags;


WORD wValue;


PVOID pAddress;


DWORD GrantedAccess;


} SYSTEM_HANDLE, PSYSTEM_HANDLE;


typedef struct _SYSTEM_HANDLE_INFORMATION {


DWORD dwCount;


SYSTEM_HANDLE Handles【1】;


} SYSTEM_HANDLE_INFORMATION, PSYSTEM_HANDLE_INFORMATION;


typedef NTSTATUS(WINAPI NTQUERYSYSTEMINFORMATION)(


IN SYSTEM_INFORMATION_CLASS SystemInformationClass,


OUT PVOID SystemInformation,


IN ULONG SystemInformationLength,


OUT PULONG ReturnLength OPTIONAL);


//typedef struct _IO_STATUS_BLOCK {


// LONG Status;


// LONG Information;


//} IO_STATUS_BLOCK, PIO_STATUS_BLOCK;


typedef struct _FILE_NAME_INFORMATION {


ULONG FileNameLength;


WCHAR FileName【MAX_PATH】;


} FILE_NAME_INFORMATION;


declspec(dllimport) LONG stdcall ZwQueryInformationFile(


IN HANDLE FileHandle,


OUT PIO_STATUS_BLOCK IoStatusBlock,


OUT PVOID FileInformation,


IN ULONG FileInformationLength,


IN ULONG FileInformationClass


);


typedef LONG(__stdcall PFN_ZwQueryInformationFile) (


IN HANDLE FileHandle,


OUT PIO_STATUS_BLOCK IoStatusBlock,


OUT PVOID FileInformation,


IN ULONG FileInformationLength,


IN ULONG FileInformationClass


);


//


// NtQueryInformationFile


//


#define FileNameInformation ((FILE_INFORMATION_CLASS)9)


// typedef struct _FILE_NAME_INFORMATION {


// ULONG FileNameLength;


// WCHAR FileName【1】;


// } FILE_NAME_INFORMATION, PFILE_NAME_INFORMATION;


typedef NTSTATUS(WINAPI NTQUERYINFORMATIONFILE)(


IN HANDLE FileHandle,


OUT PIO_STATUS_BLOCK IoStatusBlock,


OUT PVOID FileInformation,


IN ULONG Length,


IN FILE_INFORMATION_CLASS FileInformationClass);


// typedef struct _CLIENT_ID {


// HANDLE UniqueProcess;


// HANDLE UniqueThread;


// } CLIENT_ID, PCLIENT_ID;


// ncScopedHandle


class ncScopedHandle


{


ncScopedHandle(const ncScopedHandle&);


ncScopedHandle& operator=(const ncScopedHandle&);


public:


ncScopedHandle(HANDLE handle)


: _handle(handle)


{


}


~ncScopedHandle()


{


if (_handle != NULL) {


CloseHandle(_handle);


}


}


operator HANDLE() const


{


return _handle;


}


PHANDLE operator& ()


{


return &_handle;


}


void operator=(HANDLE handle)


{


if (_handle != NULL) {


CloseHandle(_handle);


}


_handle = handle;


}


private:


HANDLE _handle;


};


// ncFileHandle


struct ncFileHandle


{


SYSTEM_HANDLE _handle;//占用文件的进程句柄详细信息


tstring _filePath;//文件的完整路径,tstring等同于wstring


tstring _path;//占用进程的程序磁盘位置


ncFileHandle(SYSTEM_HANDLE handle, const tstring& filePath, const tstring& path)


: _handle(handle)


, _filePath(filePath)


, _path(path)


{


}


};


//根据文件句柄获取文件所在磁盘名


EXTERN_C BOOL GetVolumeNameByHandle(HANDLE hFile, LPWSTR szVolumeName, UINT cchMax)


{


BOOL bResult = FALSE;


WCHAR szBuf【500】 = { 0 };


WCHAR pIter = szBuf;


int i = 0;


BY_HANDLE_FILE_INFORMATION stFileInfo = { 0 };


do


{


if (FALSE == GetFileInformationByHandle(hFile, &stFileInfo)) {


break;


}


if (0 == GetLogicalDriveStringsW(_countof(szBuf), szBuf)) {


break;


}


for (; pIter; pIter += 4)


{


DWORD dwVolumeSerialNumber = 0;


if (GetVolumeInformationW(pIter, NULL, 0, &dwVolumeSerialNumber,


NULL, NULL, NULL, 0))


{


if (dwVolumeSerialNumber == stFileInfo.dwVolumeSerialNumber)


{


lstrcpynW(szVolumeName, pIter, cchMax);


bResult = TRUE;


break;


}


}


}


} while (FALSE);


return bResult;


}


EXTERN_C BOOL GetFilePathFromHandleW(HANDLE hFile, LPWSTR lpszPath, UINT cchMax)


{


BOOL bResult = FALSE;


WCHAR szValue【MAX_PATH】 = { 0 };


IO_STATUS_BLOCK isb = { 0 };


FILE_NAME_INFORMATION fni = { 0 };


HMODULE hNtDLL = NULL;


PFN_ZwQueryInformationFile pfn_ZwQueryInformationFile = NULL;


do


{


if (INVALID_HANDLE_VALUE == hFile || NULL == lpszPath || 0 == cchMax) {


break;


}


hNtDLL = LoadLibraryW(L"ntdll.dll");


if (hNtDLL == NULL)


{


break;


}


pfn_ZwQueryInformationFile = (PFN_ZwQueryInformationFile)GetProcAddress(hNtDLL, "ZwQueryInformationFile");


if (NULL == pfn_ZwQueryInformationFile) {


break;


}


// 9 == FileNameInformation


if (0 != pfn_ZwQueryInformationFile(hFile, &isb, &fni, sizeof(fni), 9)) {


break;


}


if (FALSE == GetVolumeNameByHandle(hFile, szValue, _countof(szValue))) {


break;


}


PathAppendW(szValue, fni.FileName);


lstrcpynW(lpszPath, szValue, cchMax);


bResult = TRUE;


} while (FALSE);


return bResult;


}


EXTERN_C BOOL GetFilePathFromHandleA(HANDLE hFile, LPSTR lpszPath, UINT cchMax)


{


BOOL bResult = FALSE;


WCHAR szTmep【MAX_PATH】 = { 0 };


do


{


if (INVALID_HANDLE_VALUE == hFile || NULL == lpszPath || 0 == cchMax) {


break;


}


if (FALSE == GetFilePathFromHandleW(hFile, szTmep, _countof(szTmep))) {


break;


}


if (0 == WideCharToMultiByte(CP_ACP, 0,


szTmep, lstrlenW(szTmep),


lpszPath, cchMax, NULL, NULL))


{


break;


}


bResult = TRUE;


} while (FALSE);


return bResult;


}


// GetDeviceDriveMap


void GetDeviceDriveMap(std::map& mapDeviceDrive)


{


TCHAR szDrives【512】;


if (!GetLogicalDriveStrings(_countof(szDrives) - 1, szDrives)) {


return;


}


TCHAR lpDrives = szDrives;


TCHAR szDevice【MAX_PATH】;


TCHAR szDrive【3】 = _T(" :");


do {


szDrive = lpDrives;


if (QueryDosDevice(szDrive, szDevice, MAX_PATH)) {


mapDeviceDrive【szDevice】 = szDrive;


}


while (lpDrives++);


} while (lpDrives);


}


// DevicePathToDrivePath


BOOL DevicePathToDrivePath(tstring& path)


{


static std::map mapDeviceDrive;


if (mapDeviceDrive.empty()) {


GetDeviceDriveMap(mapDeviceDrive);


}


for (std::map::const_iterator it = mapDeviceDrive.begin(); it != mapDeviceDrive.end(); ++it) {


size_t nLength = it->first.length();


if (_tcsnicmp(it->first.c_str(), path.c_str(), nLength) == 0) {


path.replace(0, nLength, it->second);


return TRUE;


}


}


return FALSE;


}


// GetHandlePath


BOOL GetHandlePath(HANDLE handle, tstring& path)


{


static NTQUERYOBJECT fpNtQueryObject =


(NTQUERYOBJECT)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryObject");


if (fpNtQueryObject == NULL) {


return FALSE;


}


DWORD dwLength = 0;


OBJECT_NAME_INFORMATION info;


NTSTATUS status = fpNtQueryObject(handle, ObjectNameInformation, &info, sizeof(info), &dwLength);


if (status != STATUS_BUFFER_OVERFLOW) {


return FALSE;


}


POBJECT_NAME_INFORMATION pInfo = (POBJECT_NAME_INFORMATION)malloc(dwLength);


while (true) {


status = fpNtQueryObject(handle, ObjectNameInformation, pInfo, dwLength, &dwLength);


if (status != STATUS_BUFFER_OVERFLOW) {


break;


}


pInfo = (POBJECT_NAME_INFORMATION)realloc(pInfo, dwLength);


}


BOOL bRes = FALSE;


if (NT_SUCCESS(status)) {


path = pInfo->Name.Buffer;


bRes = DevicePathToDrivePath(path);


}


free(pInfo);


return bRes;


}


// GetSystemHandleInfo


PSYSTEM_HANDLE_INFORMATION GetSystemHandleInfo()


{


static NTQUERYSYSTEMINFORMATION fpNtQuerySystemInformation =


(NTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQuerySystemInformation");


if (fpNtQuerySystemInformation == NULL) {


return NULL;


}


DWORD dwLength = 0;


SYSTEM_HANDLE_INFORMATION shi;


NTSTATUS status = fpNtQuerySystemInformation(SystemHandleInformation, &shi, sizeof(shi), &dwLength);


if (status != STATUS_INFO_LENGTH_MISMATCH) {


return NULL;


}


PSYSTEM_HANDLE_INFORMATION pshi = (PSYSTEM_HANDLE_INFORMATION)malloc(dwLength);


while (true) {


status = fpNtQuerySystemInformation(SystemHandleInformation, pshi, dwLength, &dwLength);


if (status != STATUS_INFO_LENGTH_MISMATCH) {


break;


}


pshi = (PSYSTEM_HANDLE_INFORMATION)realloc(pshi, dwLength);


}


if (!NT_SUCCESS(status)) {


free(pshi);


pshi = NULL;


}


return pshi;


}


//


// 检测指定句柄是否可能导致NtQueryObject卡死:


// 1.注意必须使用NtQueryInformationFile而不是NtQueryObject进行检测,否则可能导致WinXP系统


// 下进程死锁而无法结束。


//


void CheckBlockThreadFunc(void param)


{


static NTQUERYINFORMATIONFILE fpNtQueryInformationFile =


(NTQUERYINFORMATIONFILE)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryInformationFile");


if (fpNtQueryInformationFile != NULL) {


BYTE buf【1024】;


IO_STATUS_BLOCK ioStatus;


fpNtQueryInformationFile((HANDLE)param, &ioStatus, buf, 1024, FileNameInformation);


}


}


// IsBlockingHandle


BOOL IsBlockingHandle(HANDLE handle)


{


HANDLE hThread = (HANDLE)_beginthread(CheckBlockThreadFunc, 0, (void*<span style="

相关文章
|
10天前
|
存储 算法 C++
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
文章详细探讨了C++中的泛型编程与STL技术,重点讲解了如何使用模板来创建通用的函数和类,以及模板在提高代码复用性和灵活性方面的作用。
27 2
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
|
7天前
|
C++ 内存技术
[转]Visual C++内嵌swf文件并播放
[转]Visual C++内嵌swf文件并播放
|
2月前
|
安全 编译器 C++
Microsoft Visual C++ Redistributable的作用主要体现以及可以删除吗?
这些是Microsoft Visual C++不同版本的Redistributable安装包,用于32位系统,确保相关应用正常运行。它们提供C++运行时环境,简化部署流程,支持第三方库及框架,并确保应用兼容性。定期更新可修复问题并引入新功能。在空间有限或需解决程序冲突时可考虑删除,但需谨慎操作以防影响应用稳定性和兼容性。删除前请确认无应用依赖,并通过控制面板安全卸载。
84 1
Microsoft Visual C++ Redistributable的作用主要体现以及可以删除吗?
|
6天前
|
Linux API C++
超级好用的C++实用库之文件目录操作
超级好用的C++实用库之文件目录操作
14 0
|
2月前
|
NoSQL Redis
Redis AOFRW主进程问题之更新manifest文件如何解决
Redis AOFRW主进程问题之更新manifest文件如何解决
|
22天前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
14 0
|
2月前
|
人工智能 Anolis
聚焦C++20 最新标准!技术 Workshop 精彩亮点一览 | 2024 龙蜥大会
多场技术 Workshop、多位领域专家亲自授课,分享独家洞察与宝贵经验。
|
2月前
|
NoSQL 分布式数据库 Redis
Redis 进程问题之主进程更新manifest文件如何解决
Redis 进程问题之主进程更新manifest文件如何解决
|
2月前
|
SQL 关系型数据库 Shell
【一文搞懂PGSQL】3.进程和关键文件介绍
PostgreSQL采用C/S模型,拥有多种关键进程,如PM(连接管理)、SP(会话)、SysLogger(系统日志)、BgWriter(后台写)、WALWriter(预写式日志)、PgArch(归档)、AutoVacuum(自动清理)、PgStat(统计收集)和CheckPoint(检查点)。其中,PM负责连接管理,SP处理用户会话,SysLogger记录系统日志(需在`postgresql.conf`中启用),BgWriter负责脏页写盘,WALWriter处理预写式日志,PgArch负责WAL日志归
|
2月前
|
算法 C# 开发工具
《黑神话:悟空》背后的编程语言揭秘——超越C++的多元技术融合
【8月更文挑战第27天】在游戏开发领域,一款游戏的成功往往离不开其背后强大的技术支持和编程语言的精妙运用。《黑神话:悟空》作为备受瞩目的国产单机动作游戏,其开发过程不仅涉及了多种编程语言,更是一次技术创新的集中展现。然而,当我们深入探讨其开发语言时,会发现它并非仅依赖于单一的C++,而是融合了多种编程语言的优势,共同铸就了这款游戏的辉煌。
170 0

相关实验场景

更多
下一篇
无影云桌面