①、设计界面、以及列表控件变量的绑定;
控件:List Control
singleselection:True
view:report
绑定控件变量:m_TaskList
②、列表控件样式的指定:
m_TaskList.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);//设置列表视图控件的当前扩展样式
m_TaskList.InsertColumn(0, _T("进程名称"),2,100);
m_TaskList.InsertColumn(1, _T("PID"), 2, 60);
m_TaskList.InsertColumn(2, _T("文件路径"), 2, 380);
③进程的获取
#include <Tlhelp32.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
BOOL CMFCApplication17Dlg::GetProcessList()//获取进程列表
{
BOOL bResult = FALSE;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//拍摄指定进程以及这些进程使用的堆,模块和线程的快照,必须包含头文件Tlhelp32.h
if (hSnap == INVALID_HANDLE_VALUE)
return FALSE;
int idx = 0;
CString strID;
HANDLE hProcess = NULL;
PROCESSENTRY32 info = { 0 };//PROCESSENTRY32是一个结构
info.dwSize = sizeof(PROCESSENTRY32);//进程的大小
BOOL bRet = Process32First(hSnap, &info);//检索有关系统快照中遇到的第一个进程的信息
while (bRet) {
idx = m_TaskList.InsertItem(m_TaskList.GetItemCount(), _T(""));//返回新项的索引
//不清楚m_TaskList.GetItemCount()为什么逐次增加而不是固定大小
m_TaskList.SetItemText(idx, 0, info.szExeFile);//info.szExeFile是进程的可执行文件的名称
strID.Empty();
strID.Format(_T("%d"), info.th32ProcessID);//获取进程ID
m_TaskList.SetItemText(idx, 1, strID);
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, info.th32ProcessID);//获取进程句柄
if (hProcess) {
TCHAR szPath[MAX_PATH] = { 0 };
GetModuleFileNameEx(hProcess, NULL, szPath, MAX_PATH);
//检索包含指定模块的文件的标准路径,必须包含头文件psapi.h
m_TaskList.SetItemText(idx, 2, szPath);
}
bRet = Process32Next(hSnap, &info); //检索有关系统快照中遇到的下一个进程的信息
printf("%d\n", idx);
}
return TRUE;
}
④、Debug 权限提升函数:(目前没作用)
BOOL AdjustPrivileges()
{
HANDLE hToken = NULL;
TOKEN_PRIVILEGES tp = {0};
TOKEN_PRIVILEGES oldtp = {0};
DWORD dwSize = sizeof(TOKEN_PRIVILEGES);
LUID luid = {0};
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return TRUE;
else
return FALSE;
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
CloseHandle(hToken);
return FALSE;
}
tp.PrivilegeCount=1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
/* Adjust Token Privileges */
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {
CloseHandle(hToken);
return FALSE;
}
// close handles
CloseHandle(hToken);
return TRUE;
}
⑤、菜单资源的添加及编辑:
刷新列表:ID_M_REFRESH_LIST
结束此进程:ID_M_EDN_TASK
定位文件:ID_M_FIND_EXE
拷贝路径:ID_M_COPY_PATH
⑥、菜单资源的弹出:
void CMFCApplication17Dlg::OnNMRClickListPath(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
//点击行的索引
if (pNMItemActivate->iItem < 0) return;
CString strID = m_TaskList.GetItemText(pNMItemActivate->iItem, 1);//获取PID
CPoint pt;
GetCursorPos(&pt);//获取游标(鼠标的位置)
CMenu mMenu, *pMenu;
mMenu.LoadMenu(IDR_MENU);//加载菜单
pMenu = mMenu.GetSubMenu(0);//获取子菜单
if (strID == _T("0") || strID == _T("4")) //PID=0,4是系统进程,后面三项禁用
{
pMenu->EnableMenuItem(ID_M_EDN_TASK, MF_BYCOMMAND | MF_GRAYED);//禁用
pMenu->EnableMenuItem(ID_M_FIND_EXE, MF_BYCOMMAND | MF_GRAYED);
pMenu->EnableMenuItem(ID_M_COPY_PATH, MF_BYCOMMAND | MF_GRAYED);
}
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);//弹出菜单
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
}
⑦、菜单响应函数的实现:
void CMFCApplication17Dlg::OnMRefreshList()//刷新列表功能
{
for (int idx = 0; idx < m_ImgList.GetImageCount(); idx++) {
m_ImgList.Remove(idx);
}
m_TaskList.DeleteAllItems();//先删除所有内容
GetProcessList();//重新获取进程列表
// TODO: 在此添加命令处理程序代码
}
void CMFCApplication17Dlg::OnMEdnTask()//结束此进程功能
{
int idx = m_TaskList.GetSelectionMark();//检索列表视图控件的选择标记。(行)
CString strID = m_TaskList.GetItemText(idx, 1);
CString strName = m_TaskList.GetItemText(idx, 0);
int iRet = MessageBox(_T("您确定要结束 ") + strName + _T(" 吗?"), _T("友情提示"), MB_OKCANCEL);
if (iRet == IDCANCEL) return;
if (strID == _T("0") || strName == _T("4")) { //实际上这个位置的判断是多余的
MessageBox(_T("系统进程,无法结束!"), _T("提示"));
}
else {
BOOL bRet = FALSE;
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, _tstoi(strID));
if (hProcess != NULL) {
bRet = TerminateProcess(hProcess, -1);//结束进程
CloseHandle(hProcess);//关闭打开的对象句柄。
}
if (!bRet) {
MessageBox(_T("结束进程 \" ") + strName + _T(" \" 失败,请重试!"), _T("提示"));
}
else {
m_TaskList.DeleteItem(idx);//删除当前行
}
}
// TODO: 在此添加命令处理程序代码
}
void CMFCApplication17Dlg::OnMFindExe()
{
int idx = m_TaskList.GetSelectionMark();
CString strPath = m_TaskList.GetItemText(idx, 2);
if (strPath.GetLength() > 0)
ShellExecute(m_hWnd, _T("open"), _T("Explorer.exe"), _T("/select,") + strPath, NULL, SW_SHOW);//对指定文件进行打开操作
// TODO: 在此添加命令处理程序代码
}
void CMFCApplication17Dlg::OnMCopyPath()//拷贝路径
{
int idx = m_TaskList.GetSelectionMark();
CString strPath = m_TaskList.GetItemText(idx, 2);
if (!OpenClipboard()) return;//打开剪切板
if (!EmptyClipboard()) {
CloseClipboard();//关闭剪切板
return;
}
size_t cbStr = (strPath.GetLength() + 1) * sizeof(TCHAR);
HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, cbStr);//从堆中分配指定的字节数
memcpy_s(GlobalLock(hData), cbStr, strPath.LockBuffer(), cbStr);
GlobalUnlock(hData);
strPath.UnlockBuffer();
UINT uiFormat = (sizeof(TCHAR) == sizeof(WCHAR)) ? CF_UNICODETEXT : CF_TEXT;
if (::SetClipboardData(uiFormat, hData) == NULL) //以指定的剪贴板格式将数据放置在剪贴板上
{
MessageBox(_T("设置剪贴板数据失败!"));
CloseClipboard();
return;
}
CloseClipboard();
// TODO: 在此添加命令处理程序代码
}
⑧、为列表控件加上程序的前缀图标:
// H 头文件中进行图像列表的定义:
CImageList m_ImgList;
// OnInitDialog() 函数中进行图像列表的创建及设置:
m_ImgList.Create(16, 16, ILC_COLOR24, 10, 10);
m_TaskList.SetImageList(&m_ImgList, LVSIL_SMALL);
⑨、修改GetProcessList()函数为如下:
BOOL CMFCApplication17Dlg::GetProcessList()//获取进程列表
{
BOOL bResult = FALSE;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//拍摄指定进程以及这些进程使用的堆,模块和线程的快照,必须包含头文件Tlhelp32.h
if (hSnap == INVALID_HANDLE_VALUE)
return FALSE;
int idx = 0;
int imgIdx=-1;
CString strID;
HANDLE hProcess = NULL;
CString strPath, strSys(_T("SystemRoot"));
PROCESSENTRY32 info = { 0 };//PROCESSENTRY32是一个结构
info.dwSize = sizeof(PROCESSENTRY32);//进程的大小
BOOL bRet = Process32First(hSnap, &info);//检索有关系统快照中遇到的第一个进程的信息
while (bRet) {
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, info.th32ProcessID);//获取进程句柄
if (hProcess)
{
strPath.Empty();
GetModuleFileNameEx(hProcess, NULL, strPath.GetBufferSetLength(MAX_PATH), MAX_PATH);
//检索包含指定模块的文件的标准路径,必须包含头文件psapi.h
strPath.ReleaseBuffer();
strPath.TrimLeft(_T("\\?"));
if (strPath.Left(strSys.GetLength()).CompareNoCase(strSys) == 0)
{
TCHAR szWin[MAX_PATH] = { 0 };
GetWindowsDirectory(szWin, MAX_PATH);//获取Windows路径
strPath.Replace(strSys, szWin);
}
SHFILEINFO shInfo = { 0 };
SHGetFileInfo(strPath, 0, &shInfo, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON);//获取图标
imgIdx = m_ImgList.Add(shInfo.hIcon);//加入图标的位置
}
//进行列表项的插入
idx = m_TaskList.InsertItem(m_TaskList.GetItemCount(), _T(""), imgIdx);//返回新项的索引
m_TaskList.SetItemText(idx, 0, info.szExeFile);
strID.Empty();
strID.Format(_T("%d"), info.th32ProcessID);
m_TaskList.SetItemText(idx, 1, strID);
m_TaskList.SetItemText(idx, 2, strPath);
//继续遍历进程列表
bRet = Process32Next(hSnap, &info);//检索有关系统快照中遇到的下一个进程的信息
}
return TRUE;
}