С++ Получение списка процессов и путей к exe файлам

March 23rd, 2010 Begemot Posted in Программирование

Вот неожиданно понадобилось получить список из всех запущенных exe файлов. Xотя казалось бы зачем оно такое может быть надо в simple end-user utility for storing clipboard history, но оказалось что надо. Пришлось изобретать велосипед, что бы труды не пропадали – решил опубликовать.

Вкратце получаем снимок всех процессов в системе CreateToolhelp32Snapshot, итерируясь по нему, для каждого процесса делаем снимок его модулей и получаем полный путь к ехе файлу. Если полный путь не нужен, а достаточно только имени файла – то вторую часть делать не нужно.

Теперь просто код, он простой, написан для универсальности с использованием stl.

typedef  map<wstring, wstring> ProcessMappingType;

wstring GetFullPathForProcess(DWORD pid)
{
    // Take a snapshot of all modules in the specified process.
    HANDLE hModuleSnap = NULL;
    hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    if (hModuleSnap == INVALID_HANDLE_VALUE) return _T("");

    MODULEENTRY32 me32 = {0};
    me32.dwSize = sizeof(MODULEENTRY32);
    if (!::Module32First(hModuleSnap, &me32))
    {  
        ::CloseHandle(hModuleSnap);
        return _T("");
    }
    ::CloseHandle(hModuleSnap);
    return wstring(me32.szExePath);
}

ProcessMappingType GetAllRunningApplication()
{
    ProcessMappingType m;

    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap != INVALID_HANDLE_VALUE)
    {
        PROCESSENTRY32 proc;
        proc.dwSize = sizeof(PROCESSENTRY32);
        if (Process32First(hSnap, &proc))
        {
            m[proc.szExeFile] = GetFullPathForProcess(proc.th32ProcessID);
            while (Process32Next(hSnap, &proc))
                m[proc.szExeFile] = GetFullPathForProcess(proc.th32ProcessID);
        }
        else wxFAIL_MSG(wxString::Format("Error Process32First: %i", GetLastError()));
       
        ::CloseHandle(hSnap);
    }
    else  wxFAIL_MSG(wxString::Format("Error Load ToolHelp:  %i", GetLastError()));  
   
    return m;
}

Все, с вас конфетка 🙂

P.S. И еще, хорошие люди просили сослаться на скандинавский аукцион в Киеве, дык мне не трудно 🙂 А вы верите в подобное?

Related:

11 Responses to “С++ Получение списка процессов и путей к exe файлам”

  1. Ха-ха-ха… а ты проверял, как это работает, если запускать не из студии?
    А под Windows Vista/7 под пользовательским аккаунтом?
    короткое имя ты, может быть и получишь, но вот полный путь тебе не получить…
    В XP нужно установить привелегию SeDebugPrivilege, а под остальным ОС-ями так просто не сделаешь… 🙁

  2. птьфу ты так меня пугать после выхода релиза и за когда я уже вставал что бы спать идти, а тут твой коммент и я вдруг понимаю что я действительно забыл проверить под 7кой:)

    Проверил, под 7кой и под ХР, под обычным пользователем работает отлично, теперь можно и спать 🙂

  3. Это работает для процессов текущего юзера. а для системных процессов работать не будет.
    Кстати, если пишешь, что “код с использованием stl”, то зачем wx-овский код сюда приплетать?
    И цикл while лучше заменить на do … while…
    И ещё – если будут 2 процесса с одинаковым именем, но разными путями – твой код не будет правильно работать…

  4. С пунтой воюешь? 😉

  5. Может я и придираюсь,
    Но при “wstring GetFullPathForProcess()” делать “return _T(“”);” – не совсем правильно с идеологической точки зрения. По идее должно быть “return L””;” – _tchar это не всегда wide char.

    По поводу “!::Module32First(hModuleSnap, &me32)” – а что остаётся в me32, когда функция возвращает ошибку? Если мусор, то понятно, а если me32 остаётся в начальном состоянии, то можно просто пропустить:
    ::Module32First(hModuleSnap, &me32);
    ::CloseHandle(hModuleSnap);
    return wstring(me32.szExePath);//ибо вернётся пустая строка при ошибке

    Да и HANDLE’ы просится завернуть во врапперы, чтобы не писать CloseHandle каждый раз ручками.

  6. Это работает для процессов текущего юзера. а для системных процессов работать не будет.
    Кстати, если пишешь, что “код с использованием stl”, то зачем wx-овский код сюда приплетать?
    И цикл while лучше заменить на do … while…
    И ещё – если будут 2 процесса с одинаковым именем, но разными путями – твой код не будет правильно работать…

    1. Ну прости мне старому засранцу, то что забыл два wxFAIL выкинуть из версии для блога:) Я там еще забыл include нужный добавить..
    2. да согласен, мой ляп
    3. угу, тоже согласен – но для моей задачи это вполне нормально, поэтому так получилось.

  7. С пунтой воюешь? ;)

    Не, ее я уже давно победил и она мне не сильно мешала 🙂 Это для решения других проблем.

  8. Konstantin, да в принципе со всем согласен, не идеально у меня, но такой задачи и не стояло 🙂

  9. using namespace это нехорошо :\

  10. Смотря где… в cpp файле нормально.
    правда у меня в precompiled header вообще, но я планирую исправить :)))

  11. 🙂