C++解除文件占用

1.解除文件占用,其过程比较简单,当然在寻找这个过程还是吃了不少苦头的,首先呢,我们需要,遍历系统中所有的文件句柄该过程呢,就要是检测句柄类型,如果是28,则可以认为是文件,然后检测先该文件名是不是我们需要的,如果是我们需要的,则要记录下该句柄的ProcessId,然后再打开该进程,然后向该进程中注入远程线程,关掉该文件即可

现在呢,实现了,可以遍历系统中所有正在使用的文件


#include"stdafx.h"


#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <psapi.h>
#include <strsafe.h>
#include <assert.h>
#include<iostream>
#include<fstream>
using namespace std;
#pragma comment(lib,"PSAPI.LIB")
//#pragma comment(lib,"Ntoskrnl.lib")




typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID    Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;


typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE,*PSYSTEM_HANDLE;


typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE HandleInfo[1];
}SYSTEM_HANDLE_INFORMATION,*PSYSTEM_HANDLE_INFORMATION;




typedef enum _SYSTEM_INFORMATION_CLASS {


SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemNextEventIdInformation, SystemEventIdsInformation, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeperation, SystemPlugPlayBusInformation, SystemDockInformation, SystemProcessorSpeedInformation, SystemCurrentTimeZoneInformation, SystemLookasideInformation


} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;






typedef enum _FILE_INFORMATION_CLASS { 
FileDirectoryInformation                 = 1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileObjectIdInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileAttributeTagInformation,
FileTrackingInformation,
FileIdBothDirectoryInformation,
FileIdFullDirectoryInformation,
FileValidDataLengthInformation,
FileShortNameInformation,
FileIoCompletionNotificationInformation,
FileIoStatusBlockRangeInformation,
FileIoPriorityHintInformation,
FileSfioReserveInformation,
FileSfioVolumeInformation,
FileHardLinkInformation,
FileProcessIdsUsingFileInformation,
FileNormalizedNameInformation,
FileNetworkPhysicalNameInformation,
FileIdGlobalTxDirectoryInformation,
FileIsRemoteDeviceInformation,
FileAttributeCacheInformation,
FileNumaNodeInformation,
FileStandardLinkInformation,
FileRemoteProtocolInformation,
FileReplaceCompletionInformation,
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;




typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;




HANDLE hCopy;




typedef enum _OBJECT_INFORMATION_CLASS {


ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, ObjectAllInformation, ObjectDataInformation


} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;


typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR  Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;






typedef struct _OBJECT_NAME_INFORMATION {


UNICODE_STRING Name; WCHAR NameBuffer[0];


} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef long(__stdcall*PNtQueryObject)(HANDLE ObjectHandle,ULONG ObjectInformationClass,PVOID ObjectInformation,ULONG ObjectInformationLength,PULONG ReturnLength);




//声明Native API函数
typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFOMATION)(
IN SYSTEM_INFORMATION_CLASS SystemClass,
OUT LPVOID SystemInfo,
IN ULONG SystemInfoLength,
OUT PULONG ReturnLength
);








char filename[256]={0};




DWORD WINAPI GetFileName(LPVOID p )
{
int* ProcessId=(int*)p;
HMODULE hNtDll=LoadLibrary(L"ntdll.dll");
if(hNtDll==NULL)
{
return 0;
}
PNtQueryObject NtQueryObject=(PNtQueryObject)GetProcAddress(hNtDll,"NtQueryObject");
POBJECT_NAME_INFORMATION pObject=NULL;
pObject=(POBJECT_NAME_INFORMATION)HeapAlloc(GetProcessHeap(),0,MAX_PATH*2);
memset(pObject,0,MAX_PATH*2);
ULONG returnLength;
DWORD dwReturn=NtQueryObject(hCopy,ObjectNameInformation,pObject,MAX_PATH*2,&returnLength);
//将卷路径名修改成盘符路径

if((pObject->NameBuffer!=NULL)&&(dwReturn==0))
{
DWORD n=WideCharToMultiByte(CP_OEMCP,NULL,pObject->NameBuffer,-1,NULL,0,NULL,FALSE);
   char* name=new char[n+1];
memset(name,0,n+1);
WideCharToMultiByte(CP_OEMCP,NULL,pObject->NameBuffer,-1,name,n,NULL,FALSE);
char tmp[256]={0};
sprintf(tmp,"%d",ProcessId);
if(strstr(name,filename))
{
cout<<"该进程ID 是"<<*ProcessId<<endl;
}
// cout<<name<<endl;
ofstream out("E:\\result.txt",ios::app);
out.write(name,strlen(name));
out.write("\n",strlen("\n"));
out.close();
delete[] name;
}
HeapFree(GetProcessHeap(),0,pObject);
return dwReturn;
}


//根据进程ID获取当前进程所使用的所有文件的句柄
void EnumFileHandle(DWORD pid)
{
HMODULE hNtDll=LoadLibrary(L"ntdll.dll");
if(hNtDll==NULL)
{
return;
}
//开始获取,其他API地址
NTQUERYSYSTEMINFOMATION NtQuerySystemInformation=(NTQUERYSYSTEMINFOMATION)
GetProcAddress(hNtDll,"NtQuerySystemInformation");
if(NtQuerySystemInformation==NULL)
{
return;
}
//开始为我们需要信息开辟内存
DWORD nSize=4096,nReturn=0;
PSYSTEM_HANDLE_INFORMATION pHandleInfo=(PSYSTEM_HANDLE_INFORMATION) HeapAlloc(GetProcessHeap(),0,nSize);
while(NtQuerySystemInformation(SystemHandleInformation,pHandleInfo,nSize,&nReturn)==0xc0000004)
{
HeapFree(GetProcessHeap(),0,pHandleInfo);
nSize+=4096;
pHandleInfo=(PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(),0,nSize);
}
//这样就开辟成功了
//然后打开指定的进程


DWORD dwFileCount=0;
for(ULONG i=0;i<pHandleInfo->NumberOfHandles;i++)
{
PSYSTEM_HANDLE pHandle=(PSYSTEM_HANDLE)&(pHandleInfo->HandleInfo[i]);


if((pHandle->ObjectTypeNumber==0x1c)&&(pHandle->ProcessId!=4))
{
//如果是当前进程的某个文件,这说明,该进程下有文件操作
HANDLE hProcess=OpenProcess(PROCESS_DUP_HANDLE|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,pHandle->ProcessId);
if(hProcess==NULL)
{
int a=GetLastError();
// cout<<"OpenProcess "<<a<<endl;
continue;
}


if(!DuplicateHandle(hProcess,(HANDLE)pHandle->Handle,GetCurrentProcess(),&hCopy,MAXIMUM_ALLOWED,FALSE,0))
{
continue;
}
int curID=pHandle->ProcessId;
HANDLE hThread=CreateThread(NULL,0,GetFileName,(LPVOID)&curID,0,NULL);
if(WaitForSingleObject(hThread,100)==WAIT_TIMEOUT)
{
TerminateThread(hThread,0);
}
CloseHandle(hThread);
CloseHandle(hCopy);
hCopy=0;
CloseHandle(hProcess);
hProcess=0;
}
}
HeapFree(GetProcessHeap(),0,pHandleInfo);
}




bool EnableDebugPrivilege()   
{   
HANDLE hToken;   
LUID sedebugnameValue;   
TOKEN_PRIVILEGES tkp;   
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{   
return   FALSE;   
}   
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))  
{   
CloseHandle(hToken);   
return false;   
}   
tkp.PrivilegeCount = 1;   
tkp.Privileges[0].Luid = sedebugnameValue;   
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   
if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) 
{   
CloseHandle(hToken);   
return false;   
}   
return true;   
}
int main()
{
cout<<"请输入查找的文件名称"<<endl;
cin>>filename;
EnableDebugPrivilege();
HANDLE hFile1=CreateFile(L"D:\\2.txt", GENERIC_READ,0, NULL, OPEN_EXISTING, 0, NULL);
DWORD dwTmp;
WriteFile(hFile1,L"DASD",4,&dwTmp,NULL);
EnumFileHandle(::GetCurrentProcessId());
CloseHandle(hFile1);
system("pause");
return 0;
}




这样就能根据文件名称获得该文件所在的进程ID了,不足的是我们使用的是28,也就是32bit的win7的文件句柄类型,如果是其他系统,则应该注意修改之

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当我们尝试删除一个文件时,有时会收到一个错误提示,指示文件正在被进程占用,因此删除操作无法完成。这种情况通常是因为操作系统或其他程序仍在使用该文件文件被进程占用的情况可能有多种原因。其中一种可能是文件当前正在被其他程序打开或正在被其他进程使用,这可能是由于文件被用作输入或输出,或者作为其他程序的配置文件。在这种情况下,操作系统会保护文件不被删除,以避免对其他程序或系统造成损害。 为了解决这个问题,我们可以尝试以下几种方法: 1. 关闭使用文件的程序:首先,我们可以尝试关闭正在使用文件的程序。这可以通过在任务管理器中结束进程或在应用程序中关闭文件选项来实现。关闭程序后,我们可以尝试再次删除文件。 2. 重启计算机:如果无法确定哪个程序正在使用文件,我们可以尝试重启计算机。重启计算机将关闭所有正在运行的程序和进程,并释放对文件占用。在重启后,我们可以尝试删除文件。 3. 使用特殊软件:如果上述方法无效,我们可以考虑使用一些专门删除被进程占用文件的软件。这些软件可以强制关闭进程,释放对文件占用,并删除文件。 无论哪种方法,我们都需要谨慎操作,确保我们正在删除正确的文件,并且不会影响其他程序或系统的正常运行。另外,我们还应该定期清理不再需要的文件,以避免出现文件被进程占用的情况。 ### 回答2: 当我们尝试删除一个文件时,有时候会收到一个错误消息提示文件被进程占用,导致删除失败。这通常发生在文件正被另一个程序使用,因此操作系统不允许我们删除它。 当一个文件被打开并被运行的程序占用时,操作系统为了维护文件的完整性和一致性,会阻止其他程序访问或修改这个文件。这样做是为了避免数据丢失或损坏的风险。因此,当我们试图删除被占用文件时,操作系统会提示文件被进程占用。 要解决这个问题,我们需要找出并关闭占用文件的进程。有几种方法可以做到这一点: 1. 重新启动计算机:这是最简单的方法之一。通过重新启动计算机,所有正在运行的进程都会被终止,包括占用文件的进程。在计算机重新启动后,我们可以尝试删除文件。但是请注意,这种方法可能会中断其他正在进行的任务,因此请确保保存了所有正在进行的工作。 2. 使用任务管理器或进程管理工具:我们可以使用任务管理器(Windows操作系统)或类似的进程管理工具来查找和结束占用文件的进程。打开任务管理器,切换到"进程"或"详细信息"选项卡,并找到占用文件的进程。选中该进程,然后点击"结束任务"或"结束进程"按钮。完成后,尝试删除文件。 3. 修改文件名:有时,我们可以通过将文件名更改为其他名称来绕过文件占用的问题。这样做可能会解除其他进程对该文件占用,允许我们删除文件。在修改文件名之后,我们可以尝试删除文件。如果删除成功,我们还可以将文件名改回原来的名称。 无论选择哪种方法,我们应该谨慎行事,并确保不会对其他进程或文件造成不必要的干扰。此外,记得在进行任何操作之前,备份重要的文件是非常重要的,以防止意外数据丢失。 ### 回答3: 当我们尝试删除一个文件时,如果收到“文件被进程占用”或类似的错误提示,这意味着该文件正在被操作系统中的一个进程使用。这种情况可能发生在多种情况下,我将提供一些可能的原因和解决方案。 首先,可能是由于其他应用程序或后台进程正在访问该文件。这可能是因为文件正在被其他程序读取、写入或修改。解决这个问题的一种方法是找到并关闭正在使用该文件的进程。我们可以尝试通过任务管理器或类似的工具找到并终止相关进程,然后再尝试删除文件。 另一种可能性是文件被操作系统本身使用或锁定。例如,文件可能是操作系统的一部分,或者正在被用于系统的关键功能。在这种情况下,我们不能直接删除文件,因为这可能会导致系统不稳定或造成其他问题。解决这个问题的方法是在安全模式下启动计算机,并尝试删除文件。在安全模式下,操作系统和其他进程的访问权限受到限制,这可能允许我们删除被进程占用文件。 还有一种可能是文件被某个程序意外地损坏或占用。在这种情况下,我们可以尝试进行系统检测和修复。在Windows操作系统中,我们可以使用系统文件检查工具(sfc /scannow)来扫描和修复系统文件。此外,还可以尝试使用一些第三方工具来修复文件系统错误,例如磁盘清理和修复工具。 总之,当我们尝试删除一个文件时,如果收到“文件被进程占用”的错误提示,我们应该首先尝试找到并关闭正在使用该文件的进程。如果这不起作用,我们可以尝试在安全模式下删除文件,或者进行系统检测和修复。请记住,在删除文件之前,我们应该确保文件不再被任何进程使用,以免导致系统不稳定或其他问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值