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

March 23rd, 2010 Begemot

Вот неожиданно понадобилось получить список из всех запущенных 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. И еще, хорошие люди просили сослаться на скандинавский аукцион в Киеве, дык мне не трудно 🙂 А вы верите в подобное?


Ручная загрузка функций из DLL или как в программе использовать функции из Vista API

October 26th, 2009 Begemot

Наконец и до меня дошел прогресс и я все-таки решил перейти на Vista Clipboard API в своем Clipboard Manager. Логику продумал, код написал, код что-то наподобие :

if (vista)
CallNewVistaAPI();
else
UseOldAPI();

Запускаю в дебаге под XP, программа выдает ошибку и закрывается:

Clipdiary.exe – Entry Point Not Found
—————————
The procedure entry point AddClipboardFormatListener could not be located in the dynamic link library USER32.dll.

То есть даже в случае когда код не пытается вызвать новую функцию, программа все равно не запускается, плохо. Гугл мне почему-то не чем не помог, зато помогли добрые люди. Решение – не вызывать напрямую функции api появившиеся только в висте, а тихонько вручную подгружать их из USER32.dll, запоминать адреса и использовать через указатели. Мне собственно дали готовый класс для всего этого, который я переписал под свои нужды и свой стиль, и теперь могу поделиться:)

Заголовочный файл:

#pragma once

#pragma pack (push, 8)

class CDLLFunctionImports
{
public:
CDLLFunctionImports(void);

typedef BOOL (WINAPI * PADDCLIPBOARDFORMATLISTENER)(HWND);
typedef BOOL (WINAPI * PREMOVECLIPBOARDFORMATLISTENER)(HWND);

PADDCLIPBOARDFORMATLISTENER pRemoveClipboardFormatListener;
PREMOVECLIPBOARDFORMATLISTENER pAddClipboardFormatListener;

private:
void Import(void);
HMODULE GetModuleHandle(TCHAR * ModuleName);
};

extern CDLLFunctionImports DLLFunctionImports;

#pragma pack (pop)

typedef’ом определяем типы указатели на функции с нужной нам сигнатурой. В принципе, мне бы тут хватило и одного типа, но пусть уж будет два для благозвучия. Потом определяем экземпляры указателей на эти функции. Все просто. Еще объявляем глобальный объект, экземпляр нужного класса.

Файл реализации:

#include "ph.h"
#include "dllfunctionimports.h"

CDLLFunctionImports DLLFunctionImports;

CDLLFunctionImports::CDLLFunctionImports(void)
{
pAddClipboardFormatListener = NULL;
pRemoveClipboardFormatListener = NULL;

Import();
}

void CDLLFunctionImports::Import(void)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize=sizeof(OSVersionInfo);

if (GetVersionEx(&OSVersionInfo))
{
if (OSVersionInfo.dwMajorVersion >= 6)
{
HMODULE hModule = GetModuleHandle(_T("USER32.DLL"));
if (hModule != NULL)
{
pAddClipboardFormatListener = PADDCLIPBOARDFORMATLISTENER(GetProcAddress(hModule, "AddClipboardFormatListener"));
pRemoveClipboardFormatListener = PREMOVECLIPBOARDFORMATLISTENER(GetProcAddress(hModule, "RemoveClipboardFormatListener"));
}
}
}
}

HMODULE CDLLFunctionImports::GetModuleHandle(TCHAR * ModuleName)
{
HMODULE hModule = ::GetModuleHandle(ModuleName);
if (hModule == NULL)
{
hModule = ::LoadLibrary(ModuleName);
}

return hModule;
}

В конструкторе вызываем import, который убедившись что у нас подходящая версия операционки, получает и сохраняет адреса необходимых процедур. Все магия закончилась, дальше когда нам необходимо вызвать новую функцию, используем такой вызов:

DLLFunctionImports.pAddClipboardFormatListener(handle);

Пользуясь случаем, хочу сказать спасибо человеку, который это все написал и поделился кодом. Еще он написал отличный и пока еще бесплатный lightweight yet powerful icon and bitmap editor, так что если кому приходится редактировать иконки, берите, а то он скоро зарелизит и захочет денег 🙂