像枫叶一样 發表於 2025-12-15 08:39:59

C++实现支持32位和64位进程的模块枚举

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>1. 资源部分(在资源编辑器中添加控件)</li><li>2. GetModuleBaseDlg.h</li><li>3. GetModuleBaseDlg.cpp</li><li>4. 项目配置(VS2022)</li><li>5.使用方法</li></ul></div><p><strong>使用 Visual Studio 2022 (VC++ 2022) 创建 MFC 对话框应用程序</strong></p>
<p>支持查找 <strong>32位和64位</strong>进程(使用 <code>TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32</code> 同时枚举两种模块)</p>
<p>输入进程名称(例如 <code>notepad.exe</code>),点击&ldquo;查找进程&rdquo;按钮</p>
<p>在列表控件(ListCtrl)中显示该进程的所有模块名称、基址、大小、路径</p>
<p class="maodian"></p><h2>1. 资源部分(在资源编辑器中添加控件)</h2>
<p>在对话框资源(ID 为 <code>IDD_GETMODULEBASE_DIALOG</code>)中添加以下控件:</p>
<table><thead><tr><th>类型</th><th>ID</th><th>Caption</th><th>其他属性</th></tr></thead><tbody><tr><td>Edit Control</td><td>IDC_EDIT_PROCESS</td><td>(空)</td><td></td></tr><tr><td>Button</td><td>IDC_BTN_SEARCH</td><td>查找进程</td><td></td></tr><tr><td>List Control</td><td>IDC_LIST_MODULES</td><td>(空)</td><td>View: Report, 加四列(见代码)</td></tr><tr><td>Static</td><td>IDC_STATIC_TIP</td><td>输入进程名(如 notepad.exe)</td><td></td></tr></tbody></table>
<p class="maodian"></p><h2>2. GetModuleBaseDlg.h</h2>
<div class="jb51code"><pre class="brush:cpp;">#pragma once
#include &lt;tlhelp32.h&gt;
#include &lt;afxwin.h&gt;
#include &lt;afxcmn.h&gt;

class CGetModuleBaseDlg : public CDialogEx
{
public:
    CGetModuleBaseDlg(CWnd* pParent = nullptr);

    enum { IDD = IDD_GETMODULEBASE_DIALOG };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);
    virtual BOOL OnInitDialog();

    DECLARE_MESSAGE_MAP()

public:
    afx_msg void OnBnClickedBtnSearch();

private:
    DWORD GetProcessIDByName(LPCTSTR lpProcessName);
    BOOL GetAllModules(DWORD dwPID, CListCtrl&amp; listCtrl);

    CEdit    m_editProcess;
    CButtonm_btnSearch;
    CListCtrl m_listModules;
};
</pre></div>
<p class="maodian"></p><h2>3. GetModuleBaseDlg.cpp</h2>
<div class="jb51code"><pre class="brush:cpp;">#include "pch.h"
#include "GetModuleBase.h"
#include "GetModuleBaseDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CGetModuleBaseDlg::CGetModuleBaseDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_GETMODULEBASE_DIALOG, pParent)
{
}

void CGetModuleBaseDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_PROCESS, m_editProcess);
    DDX_Control(pDX, IDC_BTN_SEARCH, m_btnSearch);
    DDX_Control(pDX, IDC_LIST_MODULES, m_listModules);
}

BEGIN_MESSAGE_MAP(CGetModuleBaseDlg, CDialogEx)
    ON_BN_CLICKED(IDC_BTN_SEARCH, &amp;CGetModuleBaseDlg::OnBnClickedBtnSearch)
END_MESSAGE_MAP()

BOOL CGetModuleBaseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 设置列表控件为报告视图并添加列
    m_listModules.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

    m_listModules.InsertColumn(0, _T("模块名称"), LVCFMT_LEFT, 150);
    m_listModules.InsertColumn(1, _T("基址"),         LVCFMT_LEFT, 120);
    m_listModules.InsertColumn(2, _T("大小"),         LVCFMT_LEFT, 100);
    m_listModules.InsertColumn(3, _T("路径"),         LVCFMT_LEFT, 400);

    return TRUE;
}

// 根据进程名获取 PID(支持大小写不敏感)
DWORD CGetModuleBaseDlg::GetProcessIDByName(LPCTSTR lpProcessName)
{
    DWORD dwPID = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE)
      return 0;

    PROCESSENTRY32 pe32 = { sizeof(pe32) };
    if (Process32First(hSnapshot, &amp;pe32))
    {
      do
      {
            if (_tcsicmp(pe32.szExeFile, lpProcessName) == 0)// 不区分大小写
            {
                dwPID = pe32.th32ProcessID;
                break;
            }
      } while (Process32Next(hSnapshot, &amp;pe32));
    }

    CloseHandle(hSnapshot);
    return dwPID;
}

// 枚举指定进程的所有模块(同时支持 32/64 位模块)
BOOL CGetModuleBaseDlg::GetAllModules(DWORD dwPID, CListCtrl&amp; listCtrl)
{
    listCtrl.DeleteAllItems();

    // 同时使用 TH32CS_SNAPMODULE 和 TH32CS_SNAPMODULE32 可兼容 WOW64 进程的 32 位模块
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwPID);
    if (hSnapshot == INVALID_HANDLE_VALUE)
      return FALSE;

    MODULEENTRY32 me32 = { sizeof(me32) };
    if (Module32First(hSnapshot, &amp;me32))
    {
      int nItem = 0;
      do
      {
            CString strBase, strSize;
            strBase.Format(_T("0x%016I64X"), (ULONGLONG)me32.modBaseAddr);
            strSize.Format(_T("0x%08X"), me32.modBaseSize);

            listCtrl.InsertItem(nItem, me32.szModule);
            listCtrl.SetItemText(nItem, 1, strBase);
            listCtrl.SetItemText(nItem, 2, strSize);
            listCtrl.SetItemText(nItem, 3, me32.szExePath);

            nItem++;
      } while (Module32Next(hSnapshot, &amp;me32));
    }

    CloseHandle(hSnapshot);
    return TRUE;
}

void CGetModuleBaseDlg::OnBnClickedBtnSearch()
{
    CString strProcessName;
    m_editProcess.GetWindowText(strProcessName);
    strProcessName.Trim();

    if (strProcessName.IsEmpty())
    {
      AfxMessageBox(_T("请输入进程名称!"));
      return;
    }

    DWORD dwPID = GetProcessIDByName(strProcessName);
    if (dwPID == 0)
    {
      AfxMessageBox(_T("未找到指定进程!请确认进程名称正确(包含.exe),且进程正在运行。"));
      m_listModules.DeleteAllItems();
      return;
    }

    CString strTitle;
    strTitle.Format(_T("进程 %s (PID: %u) 的模块列表"), strProcessName, dwPID);
    SetWindowText(strTitle);

    if (!GetAllModules(dwPID, m_listModules))
    {
      AfxMessageBox(_T("枚举模块失败,可能没有足够权限。"));
      m_listModules.DeleteAllItems();
    }
}
</pre></div>
<p class="maodian"></p><h2>4. 项目配置(VS2022)</h2>
<p>项目使用 <strong>Unicode</strong> 字符集。</p>
<p>使用 MFC:项目属性 &rarr; 常规 &rarr; 使用 MFC &rarr; &ldquo;在共享 DLL 中使用 MFC&rdquo; 或 &ldquo;在静态库中使用 MFC&rdquo;。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121508382425.png" /></p>
<p class="maodian"></p><h2>5.使用方法</h2>
<ul><li>运行程序</li><li>在编辑框输入进程可执行文件名,例如:<code>notepad.exe</code>、<code>chrome.exe</code></li><li>点击&ldquo;查找进程&rdquo;</li><li>列表中会显示该进程加载的所有模块(包括主模块和 DLL)</li></ul>
<p>这样就完整实现了你要求的功能,支持 32 位和 64 位进程的模块枚举。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121508382440.png" /></p>
<p>到此这篇关于C++实现支持32位和64位进程的模块枚举的文章就介绍到这了,更多相关C++模块枚举内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>C++中强类型枚举(scoped&nbsp;enumeration)的实现</li><li>C++11作用域枚举(Scoped&nbsp;Enums)的实现示例</li><li>C++中的枚举enum类型使用示例详解</li><li>C++11中强类型枚举的使用</li><li>关于C++11中限定作用域的枚举类型的问题</li><li>C++11 强类型枚举相关总结</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: C++实现支持32位和64位进程的模块枚举