В процессе написания одной программы (как-нибудь я познакомлю вас с ней) мне понадобиля список процессов, работающих в системе. Нужен был полный путь к исполняемым файлам.

У программирующих под Windows есть два пути получения списка запущенных задач. Первый – это воспользоваться средствами библиотеки Process Status API (PSAPI). Второй — средствами библиотеки Tool Help Library.

В первом случае мы жёстко привязаны к NT- системам, то есть этот метод не работает в Windows 9x и Windows ME (тьфу, не к ночи будет упомянута), хотя взамен мы получаем некоторые бонусы, которые для конкретной нашей цели, в общем-то, не нужны.

Во втором случае мы обретаем совместимость со всей линейкой Windows за исключением разве что Windows NT 4.0 . Думаю, здесь потеря будет невелика, ибо каждый может сосчитать по пальцам места, где он видел работающей эту систему.

Итак, как вы уже, наверное, догадались, речь у нас пойдёт о втором способе.

Маленькое замечание. Предлагаемый вам ниже проект собран в среде МS VC с поддержкой юникода, поэтому некоторые названия функций и типов переменных могут показаться вам странными. Читайте про поддержку юникода в MSDN.

Собранные нами данные о процессе мы будем хранить в следующей структуре

 
struct CMemoryProcess 
{
  _TCHAR  name[MAX_PATH]; // Имя процесса
  DWORD   pID;	// Его ID 
};

Данную структуру, если это необходимо, можно значительно расширить. В нашем примере мы обойдёмся двумя полями.

Список процессов будем хранить при помощи уже описанного ранеее класса aset<>


aset	memProcesses;

Теперь, собственно, и сама функция получения списка процессов.


BOOL enumerateProcesses()
{
  HANDLE hProcessSnap;
  PROCESSENTRY32 pe32;

  // Очищаем список процессов
  memProcesses.clear(); 

  // Делаем "мгновенный снимок" всех процессов в системе
  hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

  if(hProcessSnap == INVALID_HANDLE_VALUE){

    // Если что-то не сложилось, здесь можно поставить обработчик ошибок
    return FALSE;
  }

  // Устанавливаем размер структуры перед её использованием
  pe32.dwSize = sizeof( PROCESSENTRY32 );

  // Получаем информацию о первом процессе
  if(!Process32First( hProcessSnap, &pe32)){

    // Если не вышло, обрабатываем ошибку и выходим
    // Необходимо обязательно закрыть handle 
    CloseHandle(hProcessSnap);     
    return FALSE;
  }
  // Далее получаем информацию о всех последующих процессах
  do {
    // Нам не нужен корневой процесс
    if (pe32.th32ParentProcessID) {
      HANDLE hModuleSnap = INVALID_HANDLE_VALUE;

      MODULEENTRY32 me32;
      // Получаем "мгновенный снимок" всех модулей данного процесса
      hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe32.th32ProcessID);

      if(hModuleSnap == INVALID_HANDLE_VALUE){
        // Здесь должен быть обработчик ошибок
        continue;
      }

      // Устанавливаем размер структуры перед её использованием
      me32.dwSize = sizeof(MODULEENTRY32);

      // Получаем информацию о первом модуле
      // как правило, это и есть исполняемый файл,
      // поэтому следующие модули мы просто не рассматриваем
      if(!Module32First(hModuleSnap, &me32)) {

        // Если не вышло, обрабатываем ошибку и выходим
        me32.th32ModuleID = 0;

        // Необходимо обязательно закрыть handle 
        CloseHandle( hModuleSnap );     
        break;
      }
      CloseHandle(hModuleSnap);

      // Здесь мы, собственно, и получаем информацию о процессе
      CMemoryProcess process;
      lstrcpy(process.name, me32.szExePath);
      process.pID = pe32.th32ProcessID;

      // Добавляем в хранилище
      memProcesses.add(process);
    }
  } 
  while(Process32Next(hProcessSnap, &pe32));
  CloseHandle(hProcessSnap);
  return TRUE;
}

Теперь нам осталось вызвать эту функцию из своей программы и распечатать результат.


int _tmain(int argc, _TCHAR* argv[])
{
  if (enumerateProcesses()) {
    CMemoryProcess	*pProcess = memProcesses.getFirst();
    while (pProcess) {
      _tprintf (_T("Process: %s\tID: %08x\r\n"), pProcess->name, 
                pProcess->pID); 
      pProcess = memProcesses.getNext();
    }
  }
  return 0;
}

Как видите, всё достаточно просто и прозаично. Полностью проект можно взять здесь.