if (pEnumProcesses)
if (pEnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ))
{
cProcesses = cbNeeded / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
{
// можно написать функцию, обрабатывающую каждый процесс:
// ForEachProcess(aProcesses[i]);
// или использовать массив строк:
// Здесь я не уверен что-то[i] = GetModuleFileName(aProcesses[i]);
}
}
// cleanup
if (PsapiHND) { if (FreeLibrary(PsapiHND)) PsapiHND = NULL; }
return cProcesses;
}
Во первых, psapi можно линковать и статически, а во вторых поправка к коду21.02.05 12:49 Автор: amirul <Serge> Статус: The Elderman
DWORD Processes[1024], Needed, NumProcesses;
DWORD i;
char ProcessName[MAX_PATH];
HANDLE hProcess;
HMODULE hModule;
if (!EnumProcesses(Processes, sizeof(Processes), &Needed))
goto fail;
NumProcesses = (Needed / sizeof(DWORD));
for (i = 0; i < NumProcesses; i++) {
hProcess = OpenProcess(GENERIC_ALL, FALSE, Processes[i]);
if (hProcess != NULL) {
if (EnumProcessModules(hProcess, &hModule, sizeof(hModule), &Needed)) {
GetModuleBaseName(hProcess, hModule, ProcessName, sizeof(ProcessName));
// Здесь можно использовать ProcessName
}
}
CloseHandle(hProcess);
}
return 0;
fail:
return -1;
---
Ну и для NT-систем можно напрямую использовать NtQuerySystemInformation (именно ее использует NT-шная реализация psapi)
Во первых (статическая линковка) - это дело вкуса. Во вторых - согласен НО!.21.02.05 16:46 Автор: kstati <Евгений Борисов> Статус: Elderman Отредактировано 21.02.05 16:50 Количество правок: 1
По поводу статики. Если библиотека не найдена, при динамической загрузке есть возможность отследить ошибку и нормально оповестить пользователя, при статической - полная лажа.
Кроме того goto басиком пахнет Ну и вынеси:
if (!EnumProcesses(Processes, sizeof(Processes), &Needed))
{
return -1;
}
[C++] Во первых (статическая линковка) - это дело вкуса. Во вторых - согласен НО!.21.02.05 22:35 Автор: Cyber_Onix Статус: Незарегистрированный пользователь
в моей версии достаточно и при линковке убедится, что указана библиотека kernel32.lib (по дефолту так и есть)21.02.05 23:24 Автор: kstati <Евгений Борисов> Статус: Elderman
> GetModuleBaseName(hProcess, hModule, ProcessName, > sizeof(ProcessName-1)); > > Или > char ProcessName[MAX_PATH+1]; Дык я передаю истинный размер буфера. Винда просто не завершит строку нулем (или вернет статус - недостаточно места) если ей не хватит места развернуться.
В данном конкретном случае:
[out] Pointer to the buffer that receives the base name of the module. If the base name is longer than maximum number of characters specified by the nSize parameter, the base name is truncated
> Твой код потенциально уязвим. Нет, тот что я привел не содержит уязвимости, но вот в обработке имени она уже может появиться (если надеяться на null-terminator).
> По поводу статики. Если библиотека не найдена, при > динамической загрузке есть возможность отследить ошибку и > нормально оповестить пользователя, при статической - полная > лажа. Ну дык psapi.dll она вроде стандартная.
> Кроме того goto басиком пахнет Ну и > вынеси: Ничуть. "Отец" структурного программирования и лозунгов "Долой goto" Дональд Кнут в конце концов пришел к выводу, что в некоторых случаях использование goto дает более качественный и более ПОНЯТНЫЙ код. Есть два простых правила по использованию goto: 1) Переходить только вперед 2) Переходить границы блоков (compound-statements) только в направлении выхода из них. В этом случае структурность не нарушается, а понятность возрастает
Сравни:
int i, j;
BOOL flag = FALSE;
for (i = 0; i < MAX_I; i++) {
for (j = 0; j < MAX_J; j++) {
if (some_condition) {
flag = TRUE;
break;
}
// do something
}
if (flag)
break;
}
---
и
int i, j;
BOOL flag = FALSE;
for (i = 0; i < MAX_I; i++) {
for (j = 0; j < MAX_J; j++) {
if (some_condition) {
goto some_condition_detected;
}
// do something
}
}
some_condition_detected:;
// do something more
---
Что эффективнее работает и лучше читается?
В perl-е для этого есть специальный синтаксис в самом языке.
---
Мало того, что этот метод плохо масштабируется, так он еще и потенциально подвержен ошибкам
Попытки разрешить это дело вложенными if-ами немного помогают, но когда if-ов становится штук 20 начинаешь теряться
Решение проблемы
SOME_RESOURCE res1 = INVALID_RESOURCE, res2 = INVALID_RESOURCE, res3 = INVALID_RESOURCE;
res1 = AllocateResource();
if (res1 == INVALID_RESOURCE)
goto fail;
res2 = AllocateResource();
if (res2 == INVALID_RESOURCE)
goto fail;
res3 = AllocateResource();
if (res3 == INVALID_RESOURCE) {
goto fail;
//do something
return 0;
fail:
if (res3 != INVALID_RESOURCE)
FreeResource(res3);
if (res2 != INVALID_RESOURCE)
FreeResource(res2);
if (res1 != INVALID_RESOURCE)
FreeResource(res1);
return -1;
---
Решение хорошо масштабируется, весь код обработки ошибок сведен в одно место, а не рассыпан по функции и выглядит это понятнее. В C++ для этого есть исключения и деструкторы локальных переменных.
> if (!EnumProcesses(Processes, sizeof(Processes), > &Needed)) > { > return -1; > } "Ну ты меня понял, да?" (с) народная мудрость :-)
Для "масштабов" используется try-catch )) и как я уже говорил, ты забыл про переполнение буфера во время обработки строк. Или специально оставляешь ошибку ;)21.02.05 20:59 Автор: kstati <Евгений Борисов> Статус: Elderman Отредактировано 21.02.05 23:40 Количество правок: 1
> Ошибки в моем коде НЕТ. Потому как > строку я не обрабатываю. Как я уже написал, она там может > появиться, если неаккуратно написать обработчик :-)
Люди, люди - стоп ;) Вы уже в такие дебри полезли ;)))
Но я думаю что я сам виноват, слишком общий вопрос задав...
Частный случай (и именно то что я стараюсь сделать)
Нужна функция которая при вызове будет смотреть - запущено ли определенное приложение, например mName = 'calc.exe' и возвращать 1 или 0, в зависимости от результата проверки