Win32通用控件,加载进程(PE查看器)项目初步(下)

简介: Win32通用控件,加载进程(PE查看器)项目初步

4.初始化进程窗口函数:

VOID InitProcessListView(HWND hDlg) {
  //设置窗口风格的话调用了结构体
  LV_COLUMN lv;
  HWND hListProcess;
  //初始化
  memset(&lv, 0, sizeof(LV_COLUMN));
  //获取IDC_LIST_PROCESS句柄
  hListProcess = GetDlgItem(hDlg, IDC_LIST3);
  //设置整行选中
  SendMessage(hListProcess, LVM_GETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  //第一列:
  lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  lv.pszText = (LPWSTR)TEXT("进程");           //列标题
  lv.cx = 200;             //行宽
  lv.iSubItem = 0;
  //ListView_InsertColumn(hListProcess,0,&lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
  //EnumProcess(hLostProcess);
  //第二列
  lv.pszText = (LPWSTR)TEXT("PID");
  lv.cx = 75;
  lv.iSubItem = 1;
  //ListView_InsertColumn(hListProcess, 1, &lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 1, (DWORD)&lv);
  //第三列
  lv.pszText = (LPWSTR)TEXT("镜像基址");
  lv.cx = 150;
  lv.iSubItem = 2;
  //ListView_InsertColumn(hListProcess, 2, &lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 2, (DWORD)&lv);
  //第三列
  lv.pszText = (LPWSTR)TEXT("镜像大小");
  lv.cx = 174;
  lv.iSubItem = 3;
  //ListView_InsertColumn(hListProcess, 3, &lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 3, (DWORD)&lv);
}

5.初始化模块窗口函数:

OID InitMoudleListView(HWND hDlg) {
  //设置窗口风格需要调用结构体
  LV_COLUMN lv;
  HWND hListMoudles;
  //初始化
  memset(&lv, 0, sizeof(LV_COLUMN));
  //获取模块列表句柄
  hListMoudles = GetDlgItem(hDlg, IDC_LIST_MOUDLE);
  //设置整行选中
  SendMessage(hListMoudles, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  //第一列:
  lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  lv.pszText = (LPWSTR)TEXT("模块名称");
  lv.cx = 400;
  lv.iSubItem = 0;
  //ListView_Insertcolumn(hListMoudles,0,&lv);
  SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
  //第二列:
  lv.pszText = (LPWSTR)TEXT("模块位置");
  lv.cx = 400;
  lv.iSubItem = 1;
  SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
}

我们可以发现,在初始化进程窗口和初始化模块窗口函数中,我们先写好了我们想要显示的标题,之后使用发送消息的方式使内容显示。这里我注释掉了一个,实际上这两种方式没有什么区别,都能使内容显示。

我们来看看ListView——Insertcolumn宏:

ListView——Insertcolumn

MSDN官方文档:ListView——Insertcolumn宏

void ListView_InsertColumn(
   hwnd,
   iCol,
   pcol
);
  • 功能:从列表视图控件中插入新列
  • 参数:
  • hwnd:列表视图控件的句柄。
  • iCol:新列的索引。
  • pcol:指向包含新列属性的 LVCOLUMN 结构的指针。

LVCOLUMN 结构:

MSDN官方文档:LVCOLUMN 结构

包含有关报表视图中的列的信息。

这个结构体大家到微软文档中自行查看吧,解释起来真的很费劲。

6.向列表中加假的进程

由于我们还没有学习如何加载操作系统中的所有进程,所以今天带领大家向列表中加载假的进程数据,有关如何加载操作系统真正的进程,后续会为大家讲解。

//加载进程函数
VOID EnumProcess(HWND hListProcess) {
  LV_ITEM vitem;
  //初始化,第一个进程
  memset(&vitem, 0, sizeof(LV_ITEM));
  vitem.mask = LVIF_TEXT;
  //假数据:
  vitem.pszText = (LPWSTR)TEXT("csrss.exe");
  vitem.iItem = 0;
  vitem.iSubItem = 0;
  //ListView_Insertem(hListProcess,*vitem);
  SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
  vitem.pszText = (LPWSTR)TEXT("448");
  vitem.iItem = 0;
  vitem.iSubItem = 1;
  SendMessage(hListProcess, LVM_SETITEM, 0, (DWORD)&vitem);
  //ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("56590000");
  vitem.iItem = 0;
  vitem.iSubItem = 2;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("000F0000");
  vitem.iItem = 0;
  vitem.iSubItem = 3;
  ListView_SetItem(hListProcess, &vitem);
  //第二个进程假数据:
  vitem.pszText = (LPWSTR)TEXT("QQ.exe");
  vitem.iItem = 1;
  vitem.iSubItem = 0;
  SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
  vitem.pszText = (LPWSTR)TEXT("153");
  vitem.iItem = 1;
  vitem.iSubItem = 1;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("65580000");
  vitem.iItem = 1;
  vitem.iSubItem = 2;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("001E0000");
  vitem.iItem = 1;
  vitem.iSubItem = 3;
  ListView_SetItem(hListProcess, &vitem);
  //第三个进程假数据:
  vitem.pszText = (LPWSTR)TEXT("WeChat.exe");
  vitem.iItem = 2;
  vitem.iSubItem = 0;
  SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
  vitem.pszText = (LPWSTR)TEXT("256");
  vitem.iItem = 2;
  vitem.iSubItem = 1;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("75960000");
  vitem.iItem = 2;
  vitem.iSubItem = 2;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("015B0000");
  vitem.iItem = 2;
  vitem.iSubItem = 3;
  ListView_SetItem(hListProcess, &vitem);
}

这里加载了一些假的数据。

这里有个需要尤其注意的地方: 就是在列表中显示我们加入的数据的时候,只有在第一个,我们使用SendMessage函数的时候,发送了LVM_INSERTITEM类型的消息,使用宏的时候使用了ListView_Insertem宏,在后续显示数据的时候,我们都是用的是LVM_SETITEM类型的消息,或者是使用了ListView_SetItem宏,这里要尤其注意,如果使用错误的话,是不能显示的。

我们来看看这两种消息的区别:

LVM_INSERTITEM消息

MSDN官方文档:LVM_INSERTITEM消息

  • 发送时间:在列表视图控件中插入新项。
  • 附加信息:
  • wParam:必须为0.
  • lParam:指向指定列表视图项属性的 LVITEM 结构的指针。

LVM_SETITEM消息

MSDN官方文档:LVSETITEM消息

  • 发送时间:设置列表视图项的某些或全部属性。 还可以发送LVM_SETITEM来设置子项的文本
  • 附加信息:
  • wParam:必须为0.
  • lParam:指向包含新项属性的 LVITEM 结构的指针

注意两者区别为在列表视图控件中插入新项和添加子项。

LVITEMA 结构

MSDN官方文档:LVITEMA结构

结构用途:用于指定或接收列表视图项的属性。

这个结构由于用法很多,大家自行到MSDN官方文档中查阅。

7.向模块列表中加入假的模块数据

这个函数与老师上课讲的完全一致,但是并非真的添加了数据:

VOID EnumMoudles(HWND hListProcess, WPARAM wParam, LPARAM lParam) {
  DWORD dwRowId;
  TCHAR szPid[21];
  LV_ITEM lv;
  //初始化
  memset(&lv, 0, sizeof(LV_ITEM));
  //获取选择行
  dwRowId = SendMessage(hListProcess, LVM_GETNEXTITEM,-1 , LVNI_SELECTED);
  if (dwRowId == -1) {
    MessageBox(NULL, TEXT("请选择进程"), TEXT("出错啦"), MB_OK);
    return;
  }
  //获取PID
  lv.iSubItem = 1;
  lv.pszText = szPid;
  lv.cchTextMax = 0x20;
  SendMessage(hListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);
  MessageBox(NULL, szPid, TEXT("PID"), MB_OK);
}

三.加载Windows进程应用程序项目初步完整代码

讲述了这些代码,这里给大家给出完整代码,但是由于控件的ID不同,复制的时候还需要自己改动。

// PEProcess.cpp : 定义应用程序的入口点。
//
#include "framework.h"
#include "PEProcess.h"
#include <CommCtrl.h>
#pragma comment(lib,"comctl32.lib")
HINSTANCE hIns = 0;
//程序向前声明
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);     //主窗口(对话框)回调函数
VOID InitProcessListView(HWND hDlg);       //初始化主窗口进程列表函数
VOID EnumProcess(HWND hListProcess);       //设置假的进程数据函数
VOID InitMoudleListView(HWND hDlg);        //初始化主窗口模块列表函数
VOID EnumMoudles(HWND hListProcess, WPARAM wParam, LPARAM lParam);  //设置假的模块列表函数
int APIENTRY WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR lpCmdLine,
  int nCmdShow
) {
  hIns = hInstance;
  //使用通用控件的向前声明
  INITCOMMONCONTROLSEX icex;
  icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  icex.dwICC = ICC_WIN95_CLASSES;
  InitCommonControlsEx(&icex);
  DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, (DLGPROC)MainDlgProc);
  return 0;
}
//各类函数实现
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  BOOL nRet = FALSE;
  switch (uMsg) {
    case WM_CLOSE: {
      EndDialog(hDlg, 0);
      PostQuitMessage(0);
      break;
    }
    case WM_INITDIALOG: {
      InitProcessListView(hDlg);         //设置ProcessListView的风格,初始化进程列表
      InitMoudleListView(hDlg);          //设置MoudleListView的风格,初始化模块列表
      break;
    }
    case WM_COMMAND: {
      switch (LOWORD(wParam)) {
        case IDC_BUTTON_ABOUT: {
          DialogBox(hIns, MAKEINTRESOURCE(IDD_ABOUTBOX), NULL, NULL);
        }
        case IDC_BUTTON_PE: {
          //打开新的对话框,PE查看器
          return 0;
        }
        case IDC_BUTTON_OUT: {
          EndDialog(hDlg, 0);
          PostQuitMessage(0);
          return TRUE;
        }
      }
    }
    case WM_NOTIFY: {
      NMHDR* pNMHDR = (NMHDR*)lParam;
      if (wParam == IDC_LIST_PROCESS && pNMHDR->code == NM_CLICK) {
        EnumMoudles(GetDlgItem(hDlg, IDC_LIST_PROCESS), wParam, lParam);
      }
      break;
    }
  }
  return nRet;
}
VOID InitProcessListView(HWND hDlg) {
  //设置窗口风格调用结构体
  LV_COLUMN lv;
  HWND hListProcess;
  //初始化
  memset(&lv, 0, sizeof(LV_COLUMN));
  //获取进程列表句柄
  hListProcess = GetDlgItem(hDlg, IDC_LIST_PROCESS);
  //设置整行选中
  SendMessage(hListProcess, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  //出错代码:::::
  SendMessage(hListProcess, LVM_GETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  //第一列:
  lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  lv.pszText = (LPWSTR)TEXT("进程");           //列标题
  lv.cx = 350;             //行宽
  lv.iSubItem = 0;
  //ListView_InsertColumn(hListProcess,0,&lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
  //第二列
  lv.pszText = (LPWSTR)TEXT("PID");
  lv.cx = 100;
  lv.iSubItem = 1;
  //ListView_InsertColumn(hListProcess, 1, &lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 1, (DWORD)&lv);
  //第三列
  lv.pszText = (LPWSTR)TEXT("镜像基址");
  lv.cx = 150;
  lv.iSubItem = 2;
  //ListView_InsertColumn(hListProcess, 2, &lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 2, (DWORD)&lv);
  //第四列
  lv.pszText = (LPWSTR)TEXT("镜像大小");
  lv.cx = 200;
  lv.iSubItem = 3;
  //ListView_InsertColumn(hListProcess, 3, &lv);
  SendMessage(hListProcess, LVM_INSERTCOLUMN, 3, (DWORD)&lv);
  EnumProcess(hListProcess);
}
//加载进程函数
VOID EnumProcess(HWND hListProcess) {
  LV_ITEM vitem;
  //初始化,第一个进程
  memset(&vitem, 0, sizeof(LV_ITEM));
  vitem.mask = LVIF_TEXT;
  //假数据:
  vitem.pszText = (LPWSTR)TEXT("csrss.exe");
  vitem.iItem = 0;
  vitem.iSubItem = 0;
  //ListView_Insertem(hListProcess,*vitem);
  SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
  vitem.pszText = (LPWSTR)TEXT("448");
  vitem.iItem = 0;
  vitem.iSubItem = 1;
  SendMessage(hListProcess, LVM_SETITEM, 0, (DWORD)&vitem);
  //ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("56590000");
  vitem.iItem = 0;
  vitem.iSubItem = 2;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("000F0000");
  vitem.iItem = 0;
  vitem.iSubItem = 3;
  ListView_SetItem(hListProcess, &vitem);
  //第二个进程假数据:
  vitem.pszText = (LPWSTR)TEXT("QQ.exe");
  vitem.iItem = 1;
  vitem.iSubItem = 0;
  SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
  vitem.pszText = (LPWSTR)TEXT("153");
  vitem.iItem = 1;
  vitem.iSubItem = 1;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("65580000");
  vitem.iItem = 1;
  vitem.iSubItem = 2;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("001E0000");
  vitem.iItem = 1;
  vitem.iSubItem = 3;
  ListView_SetItem(hListProcess, &vitem);
  //第三个进程假数据:
  vitem.pszText = (LPWSTR)TEXT("WeChat.exe");
  vitem.iItem = 2;
  vitem.iSubItem = 0;
  SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
  vitem.pszText = (LPWSTR)TEXT("256");
  vitem.iItem = 2;
  vitem.iSubItem = 1;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("75960000");
  vitem.iItem = 2;
  vitem.iSubItem = 2;
  ListView_SetItem(hListProcess, &vitem);
  vitem.pszText = (LPWSTR)TEXT("015B0000");
  vitem.iItem = 2;
  vitem.iSubItem = 3;
  ListView_SetItem(hListProcess, &vitem);
}
VOID InitMoudleListView(HWND hDlg) {
  //设置窗口风格需要调用结构体
  LV_COLUMN lv;
  HWND hListMoudles;
  //初始化
  memset(&lv, 0, sizeof(LV_COLUMN));
  //获取模块列表句柄
  hListMoudles = GetDlgItem(hDlg, IDC_LIST_MOUDLE);
  //设置整行选中
  SendMessage(hListMoudles, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  //第一列:
  lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  lv.pszText = (LPWSTR)TEXT("模块名称");
  lv.cx = 400;
  lv.iSubItem = 0;
  //ListView_Insertcolumn(hListMoudles,0,&lv);
  SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
  //第二列:
  lv.pszText = (LPWSTR)TEXT("模块位置");
  lv.cx = 400;
  lv.iSubItem = 1;
  SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
}
VOID EnumMoudles(HWND hListProcess, WPARAM wParam, LPARAM lParam) {
  DWORD dwRowId;
  TCHAR szPid[21];
  LV_ITEM lv;
  //初始化
  memset(&lv, 0, sizeof(LV_ITEM));
  //获取选择行
  dwRowId = SendMessage(hListProcess, LVM_GETNEXTITEM,-1 , LVNI_SELECTED);
  if (dwRowId == -1) {
    MessageBox(NULL, TEXT("请选择进程"), TEXT("出错啦"), MB_OK);
    return;
  }
  //获取PID
  lv.iSubItem = 1;
  lv.pszText = szPid;
  lv.cchTextMax = 0x20;
  SendMessage(hListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);
  MessageBox(NULL, szPid, TEXT("PID"), MB_OK);
}

程序效果:

今天的分享就到这里,如果文章中出现错误或者是本人理解不到位的地方,还请大家及时指出来,我会非常虚心地学习。希望大家共同进步!!!



相关文章
|
2月前
|
JavaScript API
使用vue3+vite+electron构建小项目介绍Electron进程间通信
使用vue3+vite+electron构建小项目介绍Electron进程间通信
467 3
|
4月前
|
人工智能 PyTorch 算法框架/工具
Xinference实战指南:全面解析LLM大模型部署流程,携手Dify打造高效AI应用实践案例,加速AI项目落地进程
【8月更文挑战第6天】Xinference实战指南:全面解析LLM大模型部署流程,携手Dify打造高效AI应用实践案例,加速AI项目落地进程
Xinference实战指南:全面解析LLM大模型部署流程,携手Dify打造高效AI应用实践案例,加速AI项目落地进程
后端登录接口使用postman,无法接收返回数据,怎样解决,认真比较与原项目的代码,看看有没有写的不一样的,问题就能解决,不要多少写,根据postman的提示先找到错误的进程,看错误进程出现在那个进程
后端登录接口使用postman,无法接收返回数据,怎样解决,认真比较与原项目的代码,看看有没有写的不一样的,问题就能解决,不要多少写,根据postman的提示先找到错误的进程,看错误进程出现在那个进程
|
7月前
|
Shell Linux
【Linux】进程实践项目(更新中) — 自主shell编写
前几篇文章,我们学习进程的相关知识:进程概念,进程替换,进程控制。熟悉了进程到底是个什么事情,接下来我们来做一个实践,来运用我们所学的相关知识。这个项目就是手搓一个shell模块,模拟实现Xshell中的命令行输入。
75 1
|
测试技术 API
【OS Pintos】Project1 项目要求说明 | 进程中止信息 | 参数传递 | 用户内存访问 | 有关项目实现的建议
【OS Pintos】Project1 项目要求说明 | 进程中止信息 | 参数传递 | 用户内存访问 | 有关项目实现的建议
166 0
|
7月前
|
消息中间件 存储 算法
【C/C++ 泡沫精选面试题04】在实际项目中,多进程和多线程如何选择?
【C/C++ 泡沫精选面试题04】在实际项目中,多进程和多线程如何选择?
240 1
|
7月前
|
消息中间件 并行计算 网络协议
探秘高效Linux C/C++项目架构:让进程、线程和通信方式助力你的代码飞跃
探秘高效Linux C/C++项目架构:让进程、线程和通信方式助力你的代码飞跃
172 0
|
7月前
|
安全 Windows 容器
win32编程 -- 进程
win32编程 -- 进程
37 0
|
7月前
|
监控 Ubuntu 应用服务中间件
强大的进程查看器:htop
强大的进程查看器:htop
232 0
|
开发框架 .NET
解决NET Core发布iis项目覆盖原有的项目时"另一个程序正在使用此文件,进程无法访问"
解决NET Core发布iis项目覆盖原有的项目时"另一个程序正在使用此文件,进程无法访问"