OpenProcess打開進程返回錯誤的問題


問題描述

      項目中需要做一個小功能:能夠查看系統中當前正在運行的進程的內存信息,如內存塊類型、分配狀態、訪問權限等。如下圖所示:

      需要的信息和上圖相差無幾。說起來也不算太難,畢竟現成的API已經提供了。我們要做的就是遍歷獲取每個進程的句柄,然后逐個打開就可以提取信息了。

排查結論

      但是,當我逐步編寫完代碼並運行時,發現什么結果也沒得到。於是乎,打開調試器下了幾個斷點跟了進去發現:GetLastError()的返回值在遇到System Process時,會返回錯誤代碼87。回頭一查MSDN,人家已然說明:當OpenProcess()給定的進程ID為0時,該函數會失敗並且GetLastError()返回的錯誤代碼是ERROR_INVALID_PARAMETER。這個錯誤代碼值就是87。另外還說明了,當給定的進程是空閑進程(Idle Process)或CSRSS進程之一時,GetLastError()返回的錯誤代碼是ERROR_ACCESS_DENIED,其值為5. 出於系統安全性考慮,操作系統禁止用戶層代碼打開這些進程。

      顯然,錯誤很明顯了。我並沒有過濾這些特殊進程,而是一股腦的全部調用OpenProcess()打開進程。而剛好,我的系統上第一個遍歷的進程就是System Process(進程ID為0)。於是程序直接跳出了而得不到任何結果。另外,我的系統是Windows 7 64位系統,網上有人說在Windows XP系統上不會出現這種錯誤,不知道真假。

      遍歷進程並打開:

HANDLE proc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (proc == INVALID_HANDLE_VALUE)
{
	assert(proc != INVALID_HANDLE_VALUE);
	return ;
}
ProcessMemory item;
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
PROCESSENTRY32 procEntry = { 0 };
procEntry.dwSize = sizeof(PROCESSENTRY32);
BOOL bRet = Process32First(proc,&procEntry);
while (bRet)
{
	hProcess = OpenProcess( PROCESS_QUERY_INFORMATION| PROCESS_VM_READ, FALSE, procEntry.th32ProcessID );
	if (NULL == hProcess) 
	{
		int ret = GetLastError();
		// skip the system process and Idle process or one of CSRSS process
		if (ret != ERROR_INVALID_PARAMETER && ret != ERROR_ACCESS_DENIED)  
			return;  // function failed for other errors
	}
	else 
	{
		if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
		{
			item.pname = procEntry.szExeFile;
			item.pid = procEntry.th32ProcessID;
			item.PageFaultCount = pmc.PageFaultCount;
			item.PagefileUsage = pmc.PagefileUsage;
			item.PeakPagefileUsage = pmc.PeakPagefileUsage;
			item.PeakWorkingSetSize = pmc.PeakWorkingSetSize;
			item.QuotaNonPagedPoolUsage = pmc.QuotaNonPagedPoolUsage;
			item.QuotaPagedPoolUsage = pmc.QuotaPagedPoolUsage;
			item.QuotaPeakNonPagedPoolUsage = pmc.QuotaPeakNonPagedPoolUsage;
			item.QuotaPeakPagedPoolUsage = pmc.QuotaPeakPagedPoolUsage;

			m_procsmem.push_back(item);
		}
	}

	bRet = Process32Next(proc, &procEntry);
}
CloseHandle(hProcess);
CloseHandle(proc);

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM