实例总结:查看虚拟内存状态
2016-08-24 15:20
211 查看
本文主要是对完成的实例的一个总结,由于长时间不接触,涉及到一些技术细节记录下来。
或者:
在使用GetBuffer()后,需要配对使用函数:relatedID.ReleaseBuffer(); [参考:GetBuffer()与ReleaseBuffer()的用法,CString]
而消息响应类中,仅需要:
本实例中并没有涉及到点击列标题排序,只实现按指定列排序。[CListCtrl 使用详细] 需要以下步骤:
实现回调的比较函数static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
设置列表项Item的Data,this->m_list.SetItemData(j, LPARAM(lpwstr[j]->GetBuffer())); 即LVITEM structure中的LPARAM lParam [LVITEM] ;需要注意的是,如果设置的值(作比较的值)是字符串的话,需要设置为指向堆上的指针,否则回调时会访问到非法内存(无意义);
调用m_list.SortItems(&SelectPrcDlg::CompareFunc, 0);第二个参数,即回调函数的最后一个参数LPARAM lParamSort;
打开进程失败,通过GetLastError()获取ErrorCode,=5时代表ERROR_ACCESS_DENIED,Access is denied。可能的原因是权限不够,可以尝试提升权限(工程设置、修改程序启动权限或者通过代码修改)。还可能是编译为win32程序,x64系统上试图打开64位程序,也会失败。另外,几个系统进程例如smss.exe、系统中断等无权访问,也会打开失败。
打开失败无法获取程序句柄,通过EnumProcesses()枚举进程无法获取程序名称,而通过进程快照的方式可获得PID对应的程序名:
根据PID获取进程信息的代码(逻辑操作是将信息列入CListCtrl内):
CEdit显示等宽字体和复选框状态问题:
64位程序指针长度为8Byte,cstrTemp.Format(L"%08X", m_systemInfo.dwPageSize);,m_systemInfo类型为SYSTEM_INFO;这里无论%0nX的n是多少,结果字符串不会显示全部,如
0x00007FFFFFFFEFFFF,这里最多只会显示到 “FFFEFFFF”,具体原因还没有找到,欢迎留言或者私信指教,感谢~。
64位程序(当然在64位系统上)的m_systemInfo.lpMinimumApplicationAddress = 0x0000000000010000,m_systemInfo.lpMaximumApplicationAddress
= 0x00007FFFFFFFEFFFF(在我机器上),当我循环获取内存信息时惊觉,这段内存(进程空间,虚拟内存)非常大,根本没法循环遍历。这个问题在编译为位程序时并不存在。这个实例到此暂时停下,需要去研究研究x64和x86的架构了。这里该如何处理,还欢迎指教~
一、对话框之间的消息传递,实现数据传递
::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 = 0x0000000000010000,m_systemInfo.lpMaximumApplicationAddress
= 0x00007FFFFFFFEFFFF(在我机器上),当我循环获取内存信息时惊觉,这段内存(进程空间,虚拟内存)非常大,根本没法循环遍历。这个问题在编译为位程序时并不存在。这个实例到此暂时停下,需要去研究研究x64和x86的架构了。这里该如何处理,还欢迎指教~
相关文章推荐
- GridView相关总结(主键绑定 行高亮 状态替换 多余字符...替代 详情查看 )
- Android实例demo1之查看手机内存状态、时间数据大小格式化
- (总结)Linux下查看Nginx Apache MySQL的并发连接数和连接状态
- (总结)Linux下查看Nginx Apache MySQL的并发连接数和连接状态
- [置顶] Android Multimedia框架总结(二十)MediaCodec状态周期及Codec与输入/输出Buffer过程(附实例)
- Android Multimedia框架总结(二十)MediaCodec状态周期及Codec与输入/输出Buffer过程(附实例)
- linux端口状态查看相关命令总结
- memcached使用总结之:telnet查看Memcached运行状态
- Linux系统中查看硬件信息与运行状态的方法总结
- Oracle 11g数据库实例开启状态总结
- Hibernate(3)——实例总结Hibernate对象的状态和ThreadLoacl封闭的session
- mysql 多实例关闭、启动、查看状态
- Spring总结实例之消息 事件
- RFID会议签到系统总结(二十)――数据窗体状态控制
- 已有类实例,现在想拥有另一个相同状态的实例,除了反序列化还有别的办法吗?
- Java内部类实例测试及总结
- 如何限制Outlook查看“忙、闲状态”?
- 实例解析C++/CLI线程之线程状态持久性
- 有关查看工作组的总结
- 从工作流状态机实践中总结状态模式使用心得(转载)