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

相关文章
|
2天前
|
开发框架 安全 .NET
技术好文共享:进程和线程的区别
技术好文共享:进程和线程的区别
|
2天前
|
网络协议 Linux Shell
技术笔记:Linux中的两种守护进程standalone和xinetd
技术笔记:Linux中的两种守护进程standalone和xinetd
|
2天前
|
Unix Shell Perl
技术心得:实例解析shell子进程(subshell)
技术心得:实例解析shell子进程(subshell)
|
2天前
|
SQL 人工智能 算法
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
|
1天前
|
C++
【C++】日期类Date(详解)②
- `-=`通过复用`+=`实现,`Date operator-(int day)`则通过创建副本并调用`-=`。 - 前置`++`和后置`++`同样使用重载,类似地,前置`--`和后置`--`也复用了`+=`和`-=1`。 - 比较运算符重载如`&gt;`, `==`, `&lt;`, `&lt;=`, `!=`,通常只需实现两个,其他可通过复合逻辑得出。 - `Date`减`Date`返回天数,通过迭代较小日期直到与较大日期相等,记录步数和符号。 ``` 这是236个字符的摘要,符合240字符以内的要求,涵盖了日期类中运算符重载的主要实现。
|
3天前
|
C++
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
7 0
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
|
1天前
|
存储 编译器 C++
【C++】类和对象④(再谈构造函数:初始化列表,隐式类型转换,缺省值
C++中的隐式类型转换在变量赋值和函数调用中常见,如`double`转`int`。取引用时,须用`const`以防修改临时变量,如`const int& b = a;`。类可以有隐式单参构造,使`A aa2 = 1;`合法,但`explicit`关键字可阻止这种转换。C++11起,成员变量可设默认值,如`int _b1 = 1;`。博客探讨构造函数、初始化列表及编译器优化,关注更多C++特性。
|
1天前
|
编译器 C++
【C++】类和对象④(类的默认成员函数:取地址及const取地址重载 )
本文探讨了C++中类的成员函数,特别是取地址及const取地址操作符重载,通常无需重载,但展示了如何自定义以适应特定需求。接着讨论了构造函数的重要性,尤其是使用初始化列表来高效地初始化类的成员,包括对象成员、引用和const成员。初始化列表确保在对象创建时正确赋值,并遵循特定的执行顺序。
|
1天前
|
C语言 C++
【C++】日期类Date(详解)③
该文介绍了C++中直接相减法计算两个日期之间差值的方法,包括确定max和min、按年计算天数、日期矫正及计算差值。同时,文章讲解了const成员函数,用于不修改类成员的函数,并给出了`GetMonthDay`和`CheckDate`的const版本。此外,讨论了流插入和流提取的重载,需在类外部定义以符合内置类型输入输出习惯,并介绍了友元机制,允许非成员函数访问类的私有成员。全文旨在深化对运算符重载、const成员和流操作的理解。
|
1天前
|
定位技术 C语言 C++
C++】日期类Date(详解)①
这篇教程讲解了如何使用C++实现一个日期类`Date`,涵盖操作符重载、拷贝构造、赋值运算符及友元函数。类包含年、月、日私有成员,提供合法性检查、获取某月天数、日期加减运算、比较运算符等功能。示例代码包括`GetMonthDay`、`CheckDate`、构造函数、拷贝构造函数、赋值运算符和相关运算符重载的实现。

相关实验场景

更多