В процессе написания одной программы (как-нибудь я познакомлю вас с ней) мне понадобиля список процессов, работающих в системе. Нужен был полный путь к исполняемым файлам.
У программирующих под 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;
}
Как видите, всё достаточно просто и прозаично. Полностью проект можно взять здесь.
Как сложно! В юниксе для этого же надо просто прочитать директорию /proc, где хранится полная информация о всех процессах. А раньше, когда ее не существовало, программе ps (типа taskmanager’а в Windows) приходилось запускаться из-под суперпользователя, чтобы иметь возможность читать физическую память в системе, и там, из каких-то структур данных ядра, она выдирала свою инфу.
Однако в юниксах от геморроя давно избавились, а венда и ныне там. [-:
02.03.2006 @ 17:15
Может, это потому, что под «вендой» можно успешно делать своё дело даже не задумываясь о существовании каких-то там процессов ?
Достали сравнивать апельсины и потрахаццо.
20.07.2006 @ 20:08
А в юниксах нельзя «делать свое дело даже не задумываясь о существовании каких-то там процессов»????????
Ты (блин) комик.
Тему читай «Как получить список процессов, запущенных в системе».
В юниксах 1001 способ получить список процессов одной строчкой и не напрягаясь.
25.10.2006 @ 13:01
Чуваки, чего спорить о чёрти чём.
Голова уже болит от бесконечных споров о том что-же всётаки гавнее вынидовс или *nix
Фигли спорить?! Их просто нужно использовать для разных задач.У каждой масса своих плюсов и недочётов.
22.12.2007 @ 23:18