工控编程吧
标题:
164上位机VC MFC强制删除已打开文件
[打印本页]
作者:
qq263946146
时间:
2016-1-14 20:48
标题:
164上位机VC MFC强制删除已打开文件
(, 下载次数: 1)
上传
点击文件名下载附件
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;//记录系统当前运行的进程信息
再添加两变量所用到的头文件与自定义结构体
#include <afxtempl.h> typedef struct _UNICODE_STRING
{WORD Length;WORD MaximumLength;PWSTR Buffer;
} UNICODE_STRING;
typedef struct _VM_COUNTERS
{
DWORD PeakVirtualSize;
DWORD VirtualSize;
DWORD PageFaultCount;
DWORD PeakWorkingSetSize;
DWORD WorkingSetSize;
DWORD QuotaPeakPagedPoolUsage;
DWORD QuotaPagedPoolUsage;
DWORD QuotaPeakNonPagedPoolUsage;
DWORD QuotaNonPagedPoolUsage;
DWORD PagefileUsage;
DWORD PeakPagefileUsage;} VM_COUNTERS;
复制代码
typedef struct _SYSTEM_THREAD
{
DWORD u1;
DWORD u2;
DWORD u3;
DWORD u4;
DWORD ProcessId;
DWORD ThreadId;
DWORD dPriority;
DWORD dBasePriority;
DWORD dContextSwitches;
DWORD dThreadState; // 2=running, 5=waiting
DWORD WaitReason;
DWORD u5;
DWORD u6;
DWORD u7;
DWORD u8;
DWORD u9;
} SYSTEM_THREAD;
typedef struct _SYSTEM_PROCESS_INFORMATION
{
DWORD dNext;
DWORD dThreadCount;
DWORD dReserved01;
DWORD dReserved02;
DWORD dReserved03;
DWORD dReserved04;
DWORD dReserved05;
DWORD dReserved06;
LARGE_INTEGER qCreateTime;
LARGE_INTEGER qUserTime;
LARGE_INTEGER qKernelTime;
UNICODE_STRING usName;
DWORD BasePriority;
DWORD dUniqueProcessId;
DWORD dInheritedFromUniqueProcessId;
DWORD dHandleCount;
DWORD dReserved07;
DWORD dReserved08;
VM_COUNTERS VmCounters;
复制代码
DWORD dCommitCharge;
SYSTEM_THREAD Threads[1];
} SYSTEM_PROCESS_INFORMATION;
typedef struct _SYSTEM_HANDLE//定义系统句柄结构
{
DWORD ProcessID;
WORD HandleType;
WORD HandleNumber;
DWORD KernelAddress;
DWORD Flags;
} SYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
DWORD Count;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION;
4.例程用到了外部的函数,所以得动态加载外部函自定些变量;
数//定义外部函数
typedef DWORD( WINAPI *funGetModuleFileNameExA)( HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize);
typedef DWORD (WINAPI *PNtQuerySystemInformation)( DWORD, VOID*, DWORD, ULONG* );
typedef DWORD (WINAPI *PNtQueryObject)( HANDLE, DWORD, VOID*, DWORD, VOID* );
再添加这些函数的变量
funGetModuleFileNameExA GetModuleFileNameEx;
PNtQuerySystemInformation NtQuerySystemInformation;//外部函数
PNtQueryObject NtQueryObject;//外部函数
并在初始化函数OnInitDialog()中时动态加载
//外部函数获取
NtQuerySystemInformation = (PNtQuerySystemInformation)GetProcAddress(GetModuleHandle(_T("ntdll.dll")),_T("NtQuerySystemInformation"));
NtQueryObject = (PNtQueryObject)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), _T("NtQueryObject"));
5,添加几个成员函数,再实现两个按钮控件功能
private://成员函数
void EnumRunningProc();
void EnumProcessOpenedFile();
BOOL GetDiviceName(LPCTSTR lpDosName, CString& szDiviceName);
BOOL CloseFileHandle(DWORD dwProcessID, HANDLE hFile);
复制代码
5.函数实体部分过长,可下载例程观看 加载要删除的文件,及文件删除操作,这两个按钮的函数部分为
void CGkbc8Dlg::OnChoose()
{
CFileDialog Dlg(TRUE, "", "", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "所有文件|*.*||");
if (Dlg.DoModal() == IDOK)
SetDlgItemText(IDC_EDIT1,Dlg.GetPathName());
}
void CGkbc8Dlg::OnDelete()
{
CString sFileName;
GetDlgItemText(IDC_EDIT1,sFileName);
if(sFileName.IsEmpty()) return; //空返回;
if (MessageBox("确实要删除文件吗?", "提示", MB_YESNO)==IDNO) return;//不删除返回;
BOOL bDeleted = DeleteFile(sFileName);//删除文件
if (bDeleted)
{
SetDlgItemText(IDC_EDIT1,"");
MessageBox("删除成功!");
return;
}
int nCheck = ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck();//是否选中强制删除
if(!nCheck)//没选中强制删除
{
MessageBox("无法删除文件!");
return;
}
//<> 强制删除部分
EnumRunningProc();//列举运行中的进程
EnumProcessOpenedFile();//列举进程打开的文件句柄
BOOL bFindFile = FALSE; //发现文件标识
DWORD dwCurProcID = GetCurrentProcessId();
HANDLE hFile; //文件句柄
UCHAR FileNames[MAX_PATH];
CString sDiviceName;
GetDiviceName(sFileName, sDiviceName);
复制代码
for (POSITION pos = m_FileHandles.GetHeadPosition(); pos != NULL;)
{
SYSTEM_HANDLE& fileHandle = m_FileHandles.GetNext(pos);
SYSTEM_PROCESS_INFORMATION* pProcInfo = NULL;
BOOL bFindRet = m_SysProcesses.Lookup(fileHandle.ProcessID, pProcInfo);//在进程中查找句柄
if (!bFindRet) continue;
hFile = (HANDLE)fileHandle.HandleNumber;
if (dwCurProcID != fileHandle.ProcessID)
{
HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, TRUE, fileHandle.ProcessID);
HANDLE hSysFile = (HANDLE)fileHandle.HandleNumber;
//复制远程进程句柄到当前进程中
DuplicateHandle(hProcess, hSysFile, GetCurrentProcess(), &hFile, 0, FALSE, DUPLICATE_SAME_ACCESS);
CloseHandle(hProcess);
}
memset(FileNames, 0, MAX_PATH);
NtQueryObject(hFile, 1, FileNames, MAX_PATH, NULL);
CloseHandle(hFile);
//判断文件是否是欲删除的文件
//首先将DOS文件名转换为设备文件名
UCHAR* pchData = FileNames;
pchData += 8;
if (wcscmp((unsigned short*)pchData, sDiviceName.AllocSysString()) == 0)
{
CloseFileHandle(fileHandle.ProcessID, (HANDLE)fileHandle.HandleNumber); //关闭文件句柄
bFindFile = TRUE;
}
sDiviceName.ReleaseBuffer(); }
if (bFindFile == FALSE)
{
for (POSITION ps = m_SysProcesses.GetStartPosition(); ps != NULL;)//判断文件是否是一个直接运行的文件
{
DWORD dwProcID;
SYSTEM_PROCESS_INFORMATION* pProcInfo = NULL;
m_SysProcesses.GetNextAssoc(ps, dwProcID, pProcInfo);
if (pProcInfo != NULL)
{
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS , TRUE, dwProcID);
if (hProcess)
{
复制代码
char chFileName[MAX_PATH] = {0};
GetModuleFileNameEx = (funGetModuleFileNameExA)GetProcAddress(GetModuleHandle(_T("Psapi.dll")), "GetModuleFileNameExA");
GetModuleFileNameEx(hProcess, NULL, chFileName, MAX_PATH);
if (strcmp(sFileName.GetBuffer(0), chFileName) == 0)//发现系统中运行的进程
{
TerminateProcess(hProcess, 0);
bFindFile = true;
}
CloseHandle(hProcess);
}
}
}
}
//<>执行文件删除
if (bFindFile == TRUE)
{
BOOL bDeleted = DeleteFile(sFileName);
if (bDeleted)
{
SetDlgItemText(IDC_EDIT1,"");
MessageBox("删除成功!");
}
else
{
DWORD wResult;
wResult = GetLastError();
}
}
}
复制代码
我们来演示功能实现过程
[iqiyi]http://player.video.qiyi.com/9b412e0baf9c71ac8ed37a87ebeae81e/0/0/w_19rte5kzc9.swf-albumId=5183634309-tvId=5183634309-isPurchase=0-cnId=12[/iqiyi]
(, 下载次数: 0)
上传
点击文件名下载附件
[note]1[/note]
欢迎光临 工控编程吧 (https://www.gkbc8.com/)
Powered by Discuz! X3.4