QQ登录

只需一步,快速开始

164上位机VC MFC强制删除已打开文件

[ 复制链接 ]

char chFileName[MAX_PATH] = {0}; GetModuleFileNameEx = (funGetModuleFileNameExA)GetProcAddress ...

char chFileName[MAX_PATH] = {0};  					GetModuleFileNameEx = (funGetModuleFileNameExA)GetProcAddress ...

164上位机VC MFC强制删除已打开文件


功能展示

大家肯定都有想删除文件,却被提示无法删除的经历,这是因为文件正在被其他程序打开使用中,我们当前例程实现强制删除文件功能,选择强制删除可删除已经打开的文件,效果如图;
要点提示
文件的删除可以用函数DeleteFile()但如果文件已经打开就会删除失败,这时我们得强制关闭打开文件的进行;

进程的强制关闭 比较繁琐 ,主要思路为:1.列举系统运行的进程;2. 列举系统所有进程打开的全部文件句柄3.逐一获取文件句柄的文件名与要删除的文件名对比,再进行相应操作
实现功能
1.新建基于对话框的应用程序
2.拖拽一编辑框ID为IDC_EDIT1,用于显示要删除文件的路径;
拖拽按钮<选择要删除文件><删除已选择文件>,选择框控件<强制删除>ID改为IDC_CHECK1,分别实现其相应功能;
3.添加两变量private://成员变量
CList<SYSTEM_HANDLE, SYSTEM_HANDLE&>m_FileHandles;//记录文件句柄
CMap< DWORD, DWORD&, SYSTEM_PROCESS_INFORMATION*,SYSTEM_PROCESS_INFORMATION*> m_SysProcesses;//记录系统当前运行的进程信息
再添加两变量所用到的头文件与自定义结构体
  1. #include <afxtempl.h> typedef struct _UNICODE_STRING
  2. {WORD  Length;WORD  MaximumLength;PWSTR Buffer;
  3. } UNICODE_STRING;
  4. typedef struct _VM_COUNTERS
  5. {
  6.         DWORD PeakVirtualSize;
  7.         DWORD VirtualSize;
  8.         DWORD PageFaultCount;
  9.         DWORD PeakWorkingSetSize;
  10.         DWORD WorkingSetSize;
  11.         DWORD QuotaPeakPagedPoolUsage;
  12.         DWORD QuotaPagedPoolUsage;
  13.         DWORD QuotaPeakNonPagedPoolUsage;
  14.         DWORD QuotaNonPagedPoolUsage;
  15.         DWORD PagefileUsage;
  16.         DWORD PeakPagefileUsage;} VM_COUNTERS;
复制代码
  1. typedef struct _SYSTEM_THREAD
  2. {
  3.         DWORD        u1;
  4.         DWORD        u2;
  5.         DWORD        u3;
  6.         DWORD        u4;
  7.         DWORD        ProcessId;
  8.         DWORD        ThreadId;
  9.         DWORD        dPriority;
  10.         DWORD        dBasePriority;
  11.         DWORD        dContextSwitches;
  12.         DWORD        dThreadState;      // 2=running, 5=waiting
  13.         DWORD        WaitReason;
  14.         DWORD        u5;
  15.         DWORD        u6;
  16.         DWORD        u7;
  17.         DWORD        u8;
  18.         DWORD        u9;
  19. } SYSTEM_THREAD;
  20. typedef struct _SYSTEM_PROCESS_INFORMATION
  21. {
  22.         DWORD          dNext;
  23.         DWORD          dThreadCount;
  24.         DWORD          dReserved01;
  25.         DWORD          dReserved02;
  26.         DWORD          dReserved03;
  27.         DWORD          dReserved04;
  28.         DWORD          dReserved05;
  29.         DWORD          dReserved06;
  30.         LARGE_INTEGER  qCreateTime;
  31.         LARGE_INTEGER  qUserTime;
  32.         LARGE_INTEGER  qKernelTime;
  33.         UNICODE_STRING usName;
  34.         DWORD               BasePriority;
  35.         DWORD          dUniqueProcessId;
  36.         DWORD          dInheritedFromUniqueProcessId;
  37.         DWORD          dHandleCount;
  38.         DWORD          dReserved07;
  39.         DWORD          dReserved08;
  40.         VM_COUNTERS    VmCounters;
  41.         
复制代码
  1. DWORD          dCommitCharge;
  2.         SYSTEM_THREAD  Threads[1];
  3. } SYSTEM_PROCESS_INFORMATION;

  4. typedef struct _SYSTEM_HANDLE//定义系统句柄结构
  5. {
  6.         DWORD        ProcessID;
  7.         WORD        HandleType;
  8.         WORD        HandleNumber;
  9.         DWORD        KernelAddress;
  10.         DWORD        Flags;
  11. } SYSTEM_HANDLE;
  12. typedef struct _SYSTEM_HANDLE_INFORMATION
  13. {
  14.         DWORD                        Count;
  15.         SYSTEM_HANDLE        Handles[1];
  16. } SYSTEM_HANDLE_INFORMATION;
  17. 4.例程用到了外部的函数,所以得动态加载外部函自定些变量;
  18. 数//定义外部函数
  19. typedef DWORD( WINAPI *funGetModuleFileNameExA)( HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize);
  20. typedef DWORD (WINAPI *PNtQuerySystemInformation)( DWORD, VOID*, DWORD, ULONG* );
  21. typedef DWORD (WINAPI *PNtQueryObject)( HANDLE, DWORD, VOID*, DWORD, VOID* );
  22. 再添加这些函数的变量
  23.         funGetModuleFileNameExA                GetModuleFileNameEx;
  24.         PNtQuerySystemInformation        NtQuerySystemInformation;//外部函数
  25.         PNtQueryObject                                NtQueryObject;//外部函数
  26. 并在初始化函数OnInitDialog()中时动态加载
  27.         //外部函数获取
  28.         NtQuerySystemInformation = (PNtQuerySystemInformation)GetProcAddress(GetModuleHandle(_T("ntdll.dll")),_T("NtQuerySystemInformation"));
  29.         NtQueryObject = (PNtQueryObject)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), _T("NtQueryObject"));
  30. 5,添加几个成员函数,再实现两个按钮控件功能
  31. private://成员函数
  32.         void EnumRunningProc();
  33.         void EnumProcessOpenedFile();
  34.         BOOL GetDiviceName(LPCTSTR lpDosName, CString& szDiviceName);
  35.         BOOL CloseFileHandle(DWORD dwProcessID, HANDLE hFile);

复制代码
  1. 5.函数实体部分过长,可下载例程观看 加载要删除的文件,及文件删除操作,这两个按钮的函数部分为
  2. void CGkbc8Dlg::OnChoose()
  3. {
  4.         CFileDialog Dlg(TRUE, "", "", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "所有文件|*.*||");
  5.         if (Dlg.DoModal() == IDOK)
  6.                 SetDlgItemText(IDC_EDIT1,Dlg.GetPathName());        
  7. }
  8. void CGkbc8Dlg::OnDelete()
  9. {
  10.         CString sFileName;
  11.         GetDlgItemText(IDC_EDIT1,sFileName);
  12.         if(sFileName.IsEmpty()) return; //空返回;
  13.         if (MessageBox("确实要删除文件吗?", "提示", MB_YESNO)==IDNO) return;//不删除返回;

  14.         BOOL bDeleted = DeleteFile(sFileName);//删除文件
  15.         if (bDeleted)
  16.         {
  17.                 SetDlgItemText(IDC_EDIT1,"");
  18.                 MessageBox("删除成功!");
  19.                 return;
  20.         }
  21.         
  22.         int nCheck = ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck();//是否选中强制删除
  23.         if(!nCheck)//没选中强制删除
  24.         {
  25.                 MessageBox("无法删除文件!");
  26.                 return;
  27.         }
  28. //<> 强制删除部分
  29.         EnumRunningProc();//列举运行中的进程
  30.         EnumProcessOpenedFile();//列举进程打开的文件句柄
  31.         BOOL    bFindFile = FALSE;        //发现文件标识
  32.         DWORD        dwCurProcID = GetCurrentProcessId();
  33.         HANDLE        hFile;                //文件句柄
  34.         UCHAR        FileNames[MAX_PATH];
  35.         CString sDiviceName;
  36.         GetDiviceName(sFileName, sDiviceName);
复制代码
  1. for (POSITION pos = m_FileHandles.GetHeadPosition(); pos != NULL;)
  2.         {
  3.                 SYSTEM_HANDLE& fileHandle = m_FileHandles.GetNext(pos);
  4.                 SYSTEM_PROCESS_INFORMATION* pProcInfo = NULL;
  5.                 BOOL bFindRet =  m_SysProcesses.Lookup(fileHandle.ProcessID, pProcInfo);//在进程中查找句柄
  6.                 if (!bFindRet)  continue;
  7.                 hFile = (HANDLE)fileHandle.HandleNumber;
  8.                 if (dwCurProcID != fileHandle.ProcessID)
  9.                 {
  10.                         HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, TRUE, fileHandle.ProcessID);        
  11.                         HANDLE hSysFile = (HANDLE)fileHandle.HandleNumber;
  12.                         //复制远程进程句柄到当前进程中
  13.                         DuplicateHandle(hProcess, hSysFile, GetCurrentProcess(), &hFile, 0, FALSE, DUPLICATE_SAME_ACCESS);
  14.                         CloseHandle(hProcess);
  15.                 }
  16.                 memset(FileNames, 0, MAX_PATH);
  17.                 NtQueryObject(hFile, 1, FileNames, MAX_PATH, NULL);
  18.                 CloseHandle(hFile);
  19.                 //判断文件是否是欲删除的文件
  20.                 //首先将DOS文件名转换为设备文件名
  21.                 UCHAR* pchData = FileNames;
  22.                 pchData += 8;
  23.                 if (wcscmp((unsigned short*)pchData, sDiviceName.AllocSysString()) == 0)
  24.                 {
  25.                         CloseFileHandle(fileHandle.ProcessID, (HANDLE)fileHandle.HandleNumber);        //关闭文件句柄
  26.                         bFindFile = TRUE;
  27.                 }
  28.                 sDiviceName.ReleaseBuffer(); }
  29.         if (bFindFile == FALSE)
  30.         {
  31.                 for (POSITION ps = m_SysProcesses.GetStartPosition(); ps != NULL;)//判断文件是否是一个直接运行的文件
  32.                 {
  33.                         DWORD dwProcID;
  34.                         SYSTEM_PROCESS_INFORMATION* pProcInfo = NULL;
  35.                         m_SysProcesses.GetNextAssoc(ps, dwProcID, pProcInfo);
  36.                         if (pProcInfo != NULL)
  37.                         {
  38.                                 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS , TRUE, dwProcID);
  39.                                 if (hProcess)
  40.                                 {
复制代码
  1. char chFileName[MAX_PATH] = {0};

  2.                                         GetModuleFileNameEx = (funGetModuleFileNameExA)GetProcAddress(GetModuleHandle(_T("Psapi.dll")), "GetModuleFileNameExA");
  3.                                         GetModuleFileNameEx(hProcess, NULL, chFileName, MAX_PATH);
  4.                                         if (strcmp(sFileName.GetBuffer(0), chFileName) == 0)//发现系统中运行的进程
  5.                                         {
  6.                                                 TerminateProcess(hProcess, 0);
  7.                                                 bFindFile = true;                                       
  8.                                         }
  9.                                         CloseHandle(hProcess);
  10.                                 }
  11.                         }
  12.                 }
  13.         }

  14.         //<>执行文件删除
  15.         if (bFindFile == TRUE)
  16.         {        
  17.                 BOOL bDeleted = DeleteFile(sFileName);
  18.                 if (bDeleted)
  19.                 {
  20.                         SetDlgItemText(IDC_EDIT1,"");
  21.                         MessageBox("删除成功!");
  22.                 }
  23.                 else
  24.                 {
  25.                         DWORD wResult;
  26.                         wResult = GetLastError();
  27.                 }
  28.         }
  29. }

复制代码
我们来演示功能实现过程
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:164.上位机VC MFC强制删除已打开文件.rar 
文件大小:121.03 KB  售价:10金币
下载权限: 不限 以上或 VIP会员   [购买捐助会员]   [充值积分]   有问题联系我

  

您的支持是我们创作的动力!  

  

您可花点闲钱积分自助任意充值

  

成为VIP会员 全站资源任意下载永久更新!


回复

使用道具 举报

快速回复 返回列表 客服中心 搜索