[WinAPI] Cum enumar procesele din sistem?

Folosire Windows API in programe C/C++ (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum enumar procesele din sistem?

Post by Ovidiu Cucu » 22 Aug 2009, 13:19

Intrebare: Cum enumar procesele care ruleaza in sistem?

Raspuns: Sunt mai multe rezolvari, prima fiind apelarea functiei EnumProcesses din biblioteca PSAPI.DLL.
In exemplul de mai jos se afiseaza la consola ID-urile proceselor din sistem.

Code: Select all

#include <windows.h>
#include <psapi.h>
#include <iostream>
#include <vector>

#pragma comment(lib, "psapi.lib") // link to PSAPI library

size_t EnumProcessIdentifiers(std::vector<DWORD>& arrIDs);
// NOTE: UNICODE not defined
int main()
{
    std::vector<DWORD> vIDs;
    const size_t count = EnumProcessIdentifiers(vIDs);
    for(size_t index = 0; index < count; index++)
    {
        std::cout << vIDs[index] << std::endl;
    }
    system("pause");
    return 0;
}

size_t EnumProcessIdentifiers(std::vector<DWORD>& vIDs)
{
    vIDs.clear();
    const DWORD cb = 1024; // assume enough
    DWORD dwBytesReturned = 0;
    DWORD dwIDs[cb];
    if(::EnumProcesses(dwIDs, cb, &dwBytesReturned))
    {
        size_t size = dwBytesReturned / sizeof(DWORD);
        vIDs.resize(size);
        for(size_t index = 0; index < size; index++)
        {
            vIDs[index] = dwIDs[index];
        }
    }
    else
    {
        DWORD dwError = ::GetLastError();
        // ... handle error
    }
    return vIDs.size();
}
Note
  • In sistemele de operare Windows 7 si Windows Server 2008 R2, functia EnumProcesses se gaseste in KERNEL32.DLL.

Vezi si



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum enumar procesele din sistem? (2)

Post by Ovidiu Cucu » 22 Aug 2009, 13:20

Alta metoda este de a folosi functii din Tool Help Library.
Exemplul urmator afiseaza pe langa identificatorii proceselor din sistem, informatii suplimentare cum ar fi numele fisierului executabil,

identificatorul procesului parinte, numarul de thread-uri care ruleaza in contextul procesului dat si prioritatea de baza a thread-urilor.

Code: Select all

#include <windows.h>
#include <Tlhelp32.h>
#include <iostream>
#include <vector>

DWORD EnumSystemProcesses(std::vector<PROCESSENTRY32>& arrIDs);
// NOTE: UNICODE not defined
int main()
{
    std::vector<PROCESSENTRY32> vProcessInfo;
    DWORD dwRet = EnumSystemProcesses(vProcessInfo);
    if(ERROR_SUCCESS != dwRet)
    {
        std::cout << "EnumProcesses error: " << dwRet << std::endl;
        system("pause");
        return dwRet;
    }
    std::cout << "Running processes: " << vProcessInfo.size() << std::endl;
    std::vector<PROCESSENTRY32>::const_iterator end = vProcessInfo.end();
    std::vector<PROCESSENTRY32>::iterator iter = vProcessInfo.begin();
    for(; iter != end; ++iter)
    {
        std::cout << "-------------------------------------------" << std::endl 
            << "Process ID: " << (*iter).th32ProcessID << std::endl
            << "Exe file: " << (*iter).szExeFile << std::endl
            << "Parent process ID: " << (*iter).th32ParentProcessID << std::endl
            << "Number of threads: " << (*iter).cntThreads << std::endl
            << "Base priority threads: " << (*iter).pcPriClassBase << std::endl;
    }
    system("pause");
    return 0;
}
DWORD EnumSystemProcesses(std::vector<PROCESSENTRY32>& vProcessInfo)
{
    vProcessInfo.clear();
    DWORD dwFlags = TH32CS_SNAPPROCESS;

    HANDLE hSnap = ::CreateToolhelp32Snapshot(dwFlags, 0);
    if(INVALID_HANDLE_VALUE == hSnap)
    {
        return ::GetLastError();
    }
    PROCESSENTRY32 processEntry = {0};
    processEntry.dwSize = sizeof(PROCESSENTRY32);
    BOOL bRet = ::Process32First(hSnap, &processEntry);
    if(! bRet)
    {
        ::CloseHandle(hSnap);
        return ::GetLastError();
    }
    do
    {   
        vProcessInfo.push_back(processEntry);
    }while(::Process32Next(hSnap, &processEntry));

    ::CloseHandle(hSnap);
    return NO_ERROR;
}
Vezi si

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

[WinAPI] Cum enumar procesele din sistem? (3)

Post by cristianamarie » 24 Aug 2009, 17:33

O alta solutie, folosind NtQuerySystemInformation.

NtFileMapping.h

Code: Select all

#ifndef __NtFileMapping_Defined__
#define __NtFileMapping_Defined__

#ifdef __cplusplus
extern "C" {
#endif

	typedef struct NTENUMPROCLIST	*PNTENUMPROCLIST;
	struct NTENUMPROCLIST
	{
		HANDLE			UniqueProcessID;
		LPWSTR			ImageName;

		PNTENUMPROCLIST	Next;
	};

	BOOL 
	WINAPI
	_NtEnumerateProcesses(
		PNTENUMPROCLIST*	ppList
	);

#ifdef __cplusplus
}
#endif

#endif	//	__NtFileMapping_Defined__
Implementarea: NtFileMapping.c

Code: Select all

#include <windows.h>
#pragma warning(disable:4201)
#include <Winternl.h>
#pragma warning(default:4201)
#ifndef STATUS_INFO_LENGTH_MISMATCH
#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
#endif // STATUS_INFO_LENGTH_MISMATCH
#ifndef STATUS_UNSUCCESSFUL
#define STATUS_UNSUCCESSFUL              ((NTSTATUS)0xC0000001L)
#endif // STATUS_UNSUCCESSFUL
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 
#endif // NT_SUCCESS

#if 0
#ifndef NTSTRSAFE_UNICODE_STRING_MAX_CCH
ifndef NTSTRSAFE_MAX_CCH
#define NTSTRSAFE_MAX_CCH       2147483647
#endif
#define NTSTRSAFE_MAX_LENGTH    (NTSTRSAFE_MAX_CCH - 1)
#define NTSTRSAFE_UNICODE_STRING_MAX_CCH	((NTSTRSAFE_MAX_LENGTH) / sizeof(WCHAR))
#else
#define NTSTRSAFE_UNICODE_STRING_MAX_CCH	((65536) / sizeof(WCHAR)) 
#endif

#include "NtFileMapping.h"

typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);

BOOL 
WINAPI
_NtEnumerateProcesses(
	PNTENUMPROCLIST*	ppList
)
{
	PNTENUMPROCLIST pList = NULL;
	PNTENUMPROCLIST pCurr = NULL;
	PNTENUMPROCLIST pHead = NULL;
	BOOL fResult = FALSE;
	long lMaxProcCount = 0;
	long lCnt = 0;
	SYSTEM_PROCESS_INFORMATION* pi = NULL;
	NTQUERYSYSTEMINFORMATION fnNtQuerySystemInformation = NULL;
	SYSTEM_PROCESS_INFORMATION *pPI = NULL;
	ULONG cbSize = 0;
	ULONG cbSizeRet = 0;
	NTSTATUS status;
	BOOL excep = FALSE;
	HANDLE pid = NULL;
	DWORD dwpid = 0;
	LPBYTE pb1;
	UNICODE_STRING us1;
	BOOL fUstrOK = FALSE;
	HMODULE hNtDll = NULL;
	BOOL fException = FALSE;

	if(ppList == NULL)
	{
		return FALSE;
	}
	*ppList = NULL;

	__try
	{
		fException = TRUE;

		hNtDll = LoadLibraryW(L"ntdll.dll");
		if(hNtDll != NULL)
		{
			fnNtQuerySystemInformation = 
				(NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, "NtQuerySystemInformation");

			if(fnNtQuerySystemInformation != NULL)
			{
				pPI = NULL;
				cbSize = 0;
				cbSizeRet = 0;

				status = (* fnNtQuerySystemInformation)(SystemProcessInformation, pPI, cbSize, &cbSizeRet);
				if(status == STATUS_INFO_LENGTH_MISMATCH)
				{
					if(cbSizeRet > 0)
					{
						cbSize = cbSizeRet;
						pPI = (SYSTEM_PROCESS_INFORMATION *)LocalAlloc(LMEM_FIXED, cbSize);
						if(pPI != NULL)
						{
							excep = FALSE;
							__try
							{
								excep = TRUE;
								status = (* fnNtQuerySystemInformation)(SystemProcessInformation, pPI, cbSize, &cbSizeRet);
								excep = FALSE;
							}
							__except(EXCEPTION_EXECUTE_HANDLER)
							{
								if(excep)
								{
									status = STATUS_UNSUCCESSFUL;
								}
							}

							if(NT_SUCCESS(status))
							{
								fResult = TRUE;

								lMaxProcCount = cbSizeRet / sizeof(SYSTEM_PROCESS_INFORMATION);
								lCnt = 0;
								pi = pPI;
								while(pi != NULL)
								{
									pid = pi->UniqueProcessId;
									dwpid = (DWORD)pid;

									//	pi->Reserved2[1] == LPCWSTR
									pb1 = (UNALIGNED BYTE *)pi;
									pb1 = pb1 
										+ sizeof(ULONG)
										+ sizeof(ULONG)
										+ sizeof(LARGE_INTEGER)
										+ sizeof(LARGE_INTEGER)
										+ sizeof(LARGE_INTEGER)
										+ sizeof(LARGE_INTEGER)
										+ sizeof(LARGE_INTEGER)
										+ sizeof(LARGE_INTEGER)
									;
									
									us1.Length = 0;
									us1.MaximumLength = 0;
									us1.Buffer = NULL;

									memcpy(&us1, pb1, sizeof(UNICODE_STRING));
									//	check string
									fUstrOK = FALSE;
									if(us1.Length % sizeof(WCHAR) != 0)
									{
										fUstrOK = FALSE;
									}
									else if(us1.MaximumLength % sizeof(WCHAR) != 0)
									{
										fUstrOK = FALSE;
									}
									else if(us1.Length > us1.MaximumLength)
									{
										fUstrOK = FALSE;
									}
									else if(us1.MaximumLength > NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR))
									{
										fUstrOK = FALSE;
									}
									else if((us1.Buffer == NULL) && (us1.Length != 0))
									{
										fUstrOK = FALSE;
									}
									else if((us1.Buffer == NULL) && (us1.MaximumLength != 0))
									{
										fUstrOK = FALSE;
									}
									else
									{
										fUstrOK = TRUE;
									}

									{
										WCHAR* szImageName = NULL;

										if(fUstrOK)
										{
											if(us1.Length == 0)
											{
												szImageName = NULL;
											}
											else
											{
												USHORT ulen = us1.Length / sizeof(WCHAR);
												szImageName = (LPWSTR)LocalAlloc(LMEM_FIXED, (ulen + 1) * sizeof(WCHAR));
												if(szImageName != NULL)
												{	
													memset(szImageName, 0, (ulen + 1) * sizeof(WCHAR));
													memcpy(szImageName, us1.Buffer, us1.Length);
												}
											}
										}
										else
										{
											szImageName = NULL;
										}

										pList = (PNTENUMPROCLIST)LocalAlloc(LMEM_FIXED, sizeof(struct NTENUMPROCLIST));
										if(pList != NULL)
										{
											pList->UniqueProcessID = pid;
											pList->ImageName = szImageName;
											pList->Next = NULL;

											if(pCurr != NULL)
											{
												pCurr->Next = pList;
											}
											pCurr = pList;

											if(pHead == NULL)
											{
												pHead = pList;
											}

											pCurr = pList;
										}
									}

									if(pi->NextEntryOffset == 0)
									{
										break;
									}
									if(lCnt > lMaxProcCount)
									{
										break;
									}

									pi = (SYSTEM_PROCESS_INFORMATION*) ((UNALIGNED BYTE *)pi + pi->NextEntryOffset);
									lCnt++;
								}
							}

							LocalFree(pPI);
						}
					}
				}
			}

			FreeLibrary(hNtDll);
		}

		fException = FALSE;
	}
	__finally {
		if(fException)
		{
			fResult = FALSE;

			__try {
				while(pHead != NULL)
				{
					pList = pHead;
					pHead = pHead->Next;

					if(pList->ImageName != NULL)
					{
						LocalFree(pList->ImageName);
					}
					LocalFree(pList);
				}
			}
			__finally {
			}
		}
	}

	*ppList = pHead;

	return fResult;
}
Si un exemplu de program care afiseaza lista proceselor la consola

Code: Select all

// ...
int wmain()
{
   PNTENUMPROCLIST   ppList = NULL;
   _NtEnumerateProcesses(&ppList);

   while(NULL != ppList)
   {
      wprintf(L"ProcessID: %u Image Name: '%s'\n", ppList->UniqueProcessID, ppList->ImageName);
      ppList = ppList->Next;
   }
   // ...
   return 0;
}
Note
  1. Pentru cine se intreaba ce e cu

    Code: Select all

    pb1 = pb1
      + sizeof(ULONG)             // -> + NextEntryOffset
      + sizeof(ULONG)             // -> + NumberOfThreads
      + sizeof(LARGE_INTEGER)     // -> + Reserved[0]
      + sizeof(LARGE_INTEGER)     // -> + Reserved[1]
      + sizeof(LARGE_INTEGER)     // -> + Reserved[2]
      + sizeof(LARGE_INTEGER)     // -> + CreateTime
      + sizeof(LARGE_INTEGER)     // -> + UserTime
      + sizeof(LARGE_INTEGER)     // -> + KernelTime
    ;
    - e ca sa ajungem la membrul ImageName al structurii SYSTEM_PROCESS_INFORMATION.

    Code: Select all

    typedef struct _SYSTEM_PROCESS_INFORMATION {
      ULONG NextEntryOffset; 
      ULONG NumberOfThreads; 
      LARGE_INTEGER Reserved[3]; 
      LARGE_INTEGER CreateTime; 
      LARGE_INTEGER UserTime; 
      LARGE_INTEGER KernelTime; 
      UNICODE_STRING ImageName; 
      KPRIORITY BasePriority; 
      HANDLE ProcessId; 
      HANDLE InheritedFromProcessId; 
      ULONG HandleCount; 
      ULONG Reserved2[2]; 
      ULONG PrivatePageCount; 
      VM_COUNTERS VirtualMemoryCounters; 
      IO_COUNTERS IoCounters; 
      SYSTEM_THREAD Threads[0];
    } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
    
    Detalii aici.
  2. (adaugata de Ovidiu Cucu) Desi in multe locuri pe net, functia NtQuerySystemInformation este trecuta la "undocumented", ea se gaseste totusi in MSDN: http://msdn.microsoft.com/en-us/library ... S.85).aspx
.
Last edited by Ovidiu Cucu on 25 Aug 2009, 21:48, edited 7 times in total.
Nuclear launch detected

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum enumar procesele din sistem? (4)

Post by Ovidiu Cucu » 25 Aug 2009, 21:46

Se poate utiliza si functia PdhEnumObjectItems din biblioteca PDH (Performance Data Helper).
Exemplu

Code: Select all

// EnumProcessNames.h
#include <list>
#include <string>

#ifdef UNICODE
#define tstring wstring
#define tcout wcout
#else
#define tstring string
#define tcout cout
#endif
PDH_STATUS EnumProcessNames(std::list<std::tstring>& processes);

Code: Select all

// EnumProcessNames.cpp
#include <windows.h>
#include <tchar.h>
#include <pdh.h>
#include <pdhmsg.h>
#include "EnumProcessNames.h"
#pragma comment(lib, "pdh.lib")
#define RETURN_IF_NOT(ret, val) if(ret != val) return ret

PDH_STATUS EnumProcessNames(std::list<std::tstring>& processes)
{
   processes.clear();
   LPCTSTR pszObjectName = _T("Process");
   LPTSTR pszCounterList = NULL;
   DWORD dwCounterListLength = 0;
   LPTSTR pszInstanceList = NULL;
   DWORD dwInstanceListLength = 0;
  
   // call PdhEnumObjectItems to find out the required buffers length
   PDH_STATUS retCode = ::PdhEnumObjectItems(NULL, NULL, pszObjectName,
      pszCounterList, &dwCounterListLength, pszInstanceList, &dwInstanceListLength,
      PERF_DETAIL_NOVICE, 0);
   
   RETURN_IF_NOT(retCode, PDH_MORE_DATA);

   // allocate buffers then call PdhEnumObjectItems again
   pszCounterList = new TCHAR[dwCounterListLength];
   pszInstanceList = new TCHAR[dwInstanceListLength];

   retCode = ::PdhEnumObjectItems(NULL, NULL, pszObjectName,
      pszCounterList, &dwCounterListLength, pszInstanceList, &dwInstanceListLength,
      PERF_DETAIL_NOVICE, 0);

   RETURN_IF_NOT(retCode, ERROR_SUCCESS);

   LPTSTR pInstance = pszInstanceList;
   while(_T('\0') != *pInstance)
   {
      std::tstring strInstance = pInstance;
      processes.push_back(strInstance);
      pInstance += 1 + strInstance.size();
   }
   delete []pszCounterList;
   delete []pszInstanceList;

   return retCode;
}

Code: Select all

// Main.cpp
#include <iostream>
#include "EnumProcessNames.h"

int _tmain()
{
   std::list<std::tstring> processes;
   PDH_STATUS retCode = EnumProcessNames(processes);
   if(ERROR_SUCCESS != retCode)
   {
      std::tcout << "EnumProcessNames error: " << retCode << std::endl;
      system("pause");
      return retCode;
   }
   const std::list<std::tstring>::const_iterator end = processes.end();
   std::list<std::tstring>::const_iterator iter = processes.begin();
   for(; iter != end; ++iter)
   {
      std::tcout << *iter << std::endl;
   }
   system("pause");
   return 0;
}
Vezi si

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum enumar procesele din sistem? (5)

Post by Ovidiu Cucu » 28 Aug 2009, 13:41

Un exemplu care utilizeaza Windows Management Instrumentation (WMI).

Code: Select all

#include <wbemidl.h>
#include <tchar.h>
#include <iostream>
#include <comutil.h>

#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "comsuppw.lib")

HRESULT DisplayProcesses()
{
   // initializes COM library
   HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
   if(FAILED(hr))
   {
      return hr;
   }
   // initialize the IWbemLocator interface
   IWbemLocator *pLoc = NULL;
   hr = CoCreateInstance(CLSID_WbemLocator, NULL, 
      CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
   if(FAILED(hr))
   {
      CoUninitialize();
      return hr;
   }
   // create a connection to WMI namespace.
   IWbemServices *pSvc = NULL;
   hr = pLoc->ConnectServer(bstr_t("ROOT\\CIMV2"), 
      NULL, NULL, 0, NULL, 0, 0, &pSvc);
   if(FAILED(hr))
   {
      pLoc->Release();
      CoUninitialize();
      return hr;
   }
   // set security levels on the proxy
   hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
      NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
   if(FAILED(hr))
   {
      pSvc->Release();
      pLoc->Release();     
      CoUninitialize();
      return hr;
   }
   // do query
   IEnumWbemClassObject* pEnum = NULL;
   hr = pSvc->ExecQuery(bstr_t("WQL"), 
      bstr_t("SELECT Name, ProcessId, ExecutablePath FROM Win32_Process"),
      WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, 
      NULL,
      &pEnum);

   if(FAILED(hr))
   {
      pSvc->Release();
      pLoc->Release();
      CoUninitialize();
      return hr;
   }
   // get each processes enumeration
   IWbemClassObject *pclsObj;
   ULONG uReturn = 0;
   while(pEnum)
   {
      pEnum->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
      if(0 == uReturn)
         break;

      // get properties values
      VARIANT vtName, vtDescription, vtProcessId, vtExecutablePath;
      pclsObj->Get(L"Name", 0, &vtName, 0, 0);
      pclsObj->Get(L"ProcessId", 0, &vtProcessId, 0, 0);
      pclsObj->Get(L"ExecutablePath", 0, &vtExecutablePath, 0, 0);
      // display process info
      std::wcout << L"-----------------------------------------" << std::endl;
      std::wcout << L"Name: " <<  vtName.bstrVal << std::endl;
      std::wcout << L"ProcessId: " << vtProcessId.lVal << std::endl;
      std::wcout << L"ExecutablePath: " << ((VT_NULL == vtExecutablePath.vt) ?
         L"N/A" : vtExecutablePath.bstrVal) << std::endl;

      VariantClear(&vtName);
      VariantClear(&vtProcessId);
      VariantClear(&vtExecutablePath);
   }
   // cleanup
   pclsObj->Release();
   pEnum->Release();
   pSvc->Release();
   pLoc->Release();     
   CoUninitialize();
   return hr;
}

Vezi si

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: [WinAPI] Cum enumar procesele din sistem? (6)

Post by Ovidiu Cucu » 28 Oct 2011, 10:13

Utilizand RDS (Remote Desktop Services) API.

Exemplu

Code: Select all

#include <iostream>
#include <windows.h>
#include <Wtsapi32.h>
#pragma comment(lib, "Wtsapi32.lib")

DWORD _DisplayProcessesW()
{
   PWTS_PROCESS_INFOW pProcessInfo = NULL;
   DWORD dwCount = 0;
   // RD Session Host server on which application is running:
   HANDLE hServer = WTS_CURRENT_SERVER_HANDLE; 

   if(! ::WTSEnumerateProcessesW(hServer, 0, 1, &pProcessInfo, &dwCount))
      return ::GetLastError();
   
   PWTS_PROCESS_INFOW pi = pProcessInfo;
   for(DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++)
   {
      std::wcout << L"--------------------------" << std::endl 
         << L"Process Name: " << pi->pProcessName << std::endl 
         << L"Process Id: " << pi->ProcessId << std::endl; 
      pi++; // next
   }
   ::WTSFreeMemory(pProcessInfo);
   return NO_ERROR;
}
Vezi si
<< Back to Windows API Index

Post Reply