实例总结:查看虚拟内存状态

本文主要是对完成的实例的一个总结,由于长时间不接触,涉及到一些技术细节记录下来。

一、对话框之间的消息传递,实现数据传递

::SendMessage(this->GetParent()->m_hWnd, WM_C_SELECT_PROCESS, WPARAM(), LPARAM(relatedID.GetBuffer()));

或者:

this->GetParent()->SendMessage(WM_C_SELECT_PROCESS, WPARAM(), LPARAM(relatedID.GetBuffer()));

在使用GetBuffer()后,需要配对使用函数:relatedID.ReleaseBuffer(); [参考:GetBuffer()与ReleaseBuffer()的用法,CString]

而消息响应类中,仅需要:

BEGIN_MESSAGE_MAP(CMenmoryViewToolDlg, CDialogEx)
    ON_MESSAGE(WM_C_SELECT_PROCESS, OnCustomSelectProcess)
END_MESSAGE_MAP()

二、CListCtrl按列排序问题 

本实例中并没有涉及到点击列标题排序,只实现按指定列排序。[CListCtrl 使用详细] 需要以下步骤:

  • 实现回调的比较函数static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)

int CALLBACK SelectPrcDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	UNREFERENCED_PARAMETER(lParamSort);
	CListCtrl* pListCtrl = (CListCtrl*)lParamSort;
	CString strItem1((LPWSTR)lParam1);
	CString strItem2((LPWSTR)lParam2);
	return wcscmp(strItem1, strItem2);
}

  • 设置列表项Item的Data,this->m_list.SetItemData(j, LPARAM(lpwstr[j]->GetBuffer())); 即LVITEM structure中的LPARAM lParam [LVITEM] ;需要注意的是,如果设置的值(作比较的值)是字符串的话,需要设置为指向堆上的指针,否则回调时会访问到非法内存(无意义);
  • 调用m_list.SortItems(&SelectPrcDlg::CompareFunc, 0);第二个参数,即回调函数的最后一个参数LPARAM lParamSort;

三、打开进程OpenProcess

打开进程失败,通过GetLastError()获取ErrorCode,=5时代表ERROR_ACCESS_DENIED,Access is denied。可能的原因是权限不够,可以尝试提升权限(工程设置、修改程序启动权限或者通过代码修改)。还可能是编译为win32程序,x64系统上试图打开64位程序,也会失败。另外,几个系统进程例如smss.exe、系统中断等无权访问,也会打开失败。

打开失败无法获取程序句柄,通过EnumProcesses()枚举进程无法获取程序名称,而通过进程快照的方式可获得PID对应的程序名:

PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);			// 在使用这个结构之前,先设置它的大小  

// 给系统内的所有进程拍一个快照  
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
	printf(" CreateToolhelp32Snapshot调用失败! \n");
	return FALSE;
}

// 遍历进程快照,轮流显示每个进程的信息  
BOOL bMore = ::Process32First(hProcessSnap, &pe32);
while (bMore)
{
	this->GetProcessInfo(pe32.th32ProcessID, pe32.szExeFile);<span style="white-space:pre">	</span>// 该函数在后文
	bMore = ::Process32Next(hProcessSnap, &pe32);
}

// 不要忘记清除掉snapshot对象  
::CloseHandle(hProcessSnap);

根据PID获取进程信息的代码(逻辑操作是将信息列入CListCtrl内):

VOID SelectPrcDlg::GetProcessInfo(DWORD pid, CString processName)
{
	int index = this->m_list.GetItemCount();
	HMODULE hMods[MAX_CLASS_NAME] = { 0 };
	DWORD cbNeededModule = 0;
	WCHAR szModuleName[MAX_CLASS_NAME] = { 0 };
	PROCESS_MEMORY_COUNTERS ProcessMemCounters;

	// 通过进程ID打开进程
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
	if (hProcess == NULL)
	{
		CString cstrFailed;
		DWORD dwErr = GetLastError();
		cstrFailed.AppendFormat(L"访问[%s]失败,ErrorCode::%d ", processName, dwErr);

		wcscpy_s(szModuleName, cstrFailed);
	}

	if (hProcess != NULL)
	{
		// 枚举进程模块信息
		::EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeededModule);
		// 取得主模块名称,即进程名
		::GetModuleFileNameEx(hProcess, hMods[0], szModuleName, sizeof(szModuleName));
		// 取得进程的内存使用信息
		::GetProcessMemoryInfo(hProcess, &ProcessMemCounters, sizeof(ProcessMemCounters));
		// 获取进程PID
		//cbPid = ::GetProcessId(hProcess);

		// 关闭进程句柄
		CloseHandle(hProcess);
	}

	// 显示结果
	CString cstrProcess;
	cstrProcess.AppendFormat(L"[%d]", pid);
	this->m_list.InsertItem(index, cstrProcess);
	this->m_list.SetItemText(index, 1, szModuleName);
	m_dataBuffer[index] = new struct _Data;
	m_dataBuffer[index]->szModuleName = szModuleName;
	m_dataBuffer[index]->dwProcessId = pid;
	this->m_list.SetItemData(index, LPARAM(m_dataBuffer[index]));

	return;
}

四、访问指定进程内存信息

  • CEdit显示等宽字体和复选框状态问题:

	HFONT hFont = (HFONT)::GetStockObject(SYSTEM_FIXED_FONT);
	CFont *pFont = CFont::FromHandle(hFont);

	m_edit.SetFont(pFont);

<span style="white-space:pre">	((CButton*)this->GetDlgItem(IDC_CHECK1))->SetCheck(BST_CHECKED);</span>
  • 64位程序指针长度为8Byte,cstrTemp.Format(L"%08X", m_systemInfo.dwPageSize);,m_systemInfo类型为SYSTEM_INFO;这里无论%0nX的n是多少,结果字符串不会显示全部,如 0x00007FFFFFFFEFFFF,这里最多只会显示到 “FFFEFFFF”,具体原因还没有找到,欢迎留言或者私信指教,感谢~。
  • 64位程序(当然在64位系统上)的m_systemInfo.lpMinimumApplicationAddress = 0x0000000000010000m_systemInfo.lpMaximumApplicationAddress = 0x00007FFFFFFFEFFFF(在我机器上),当我循环获取内存信息时惊觉,这段内存(进程空间,虚拟内存)非常大,根本没法循环遍历。这个问题在编译为位程序时并不存在。这个实例到此暂时停下,需要去研究研究x64和x86的架构了。这里该如何处理,还欢迎指教~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值