技术好文: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="

相关文章
|
1月前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
38 0
|
2月前
|
存储 算法 C++
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
文章详细探讨了C++中的泛型编程与STL技术,重点讲解了如何使用模板来创建通用的函数和类,以及模板在提高代码复用性和灵活性方面的作用。
51 2
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
|
1月前
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
32 0
Linux c/c++之IPC进程间通信
|
1月前
|
Linux C++
Linux c/c++进程间通信(1)
这篇文章介绍了Linux下C/C++进程间通信的几种方式,包括普通文件、文件映射虚拟内存、管道通信(FIFO),并提供了示例代码和标准输入输出设备的应用。
30 0
Linux c/c++进程间通信(1)
|
1月前
|
Linux C++
Linux c/c++之进程的创建
这篇文章介绍了在Linux环境下使用C/C++创建进程的三种方式:system函数、fork函数以及exec族函数,并展示了它们的代码示例和运行结果。
40 0
Linux c/c++之进程的创建
|
1月前
|
Linux C++
Linux c/c++文件的基本操作
在Linux环境下使用C/C++进行文件的基本操作,包括文件的创建、写入、读取、关闭以及文件描述符的定位。
20 0
Linux c/c++文件的基本操作
|
2月前
|
C++ 内存技术
[转]Visual C++内嵌swf文件并播放
[转]Visual C++内嵌swf文件并播放
|
1月前
|
Linux C++
Linux c/c++进程之僵尸进程和守护进程
这篇文章介绍了Linux系统中僵尸进程和守护进程的概念、产生原因、解决方法以及如何创建守护进程。
23 0
|
1月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
49 0
|
1月前
|
Linux C++
Linux c/c++文件移动
这篇文章介绍了在Linux环境下,使用C/C++语言通过命令方式和文件操作方式实现文件移动的方法。
70 0
下一篇
无影云桌面