Last Updated 2002/12/05
Programming Tips Visual C++ API  索 引 
PSAPI
2002/12/05

PSAPI とは,WindowsNT4.0 にて,Process/Thread を列挙したり EXE 名を取得したりできる DLLである.(詳しくは MSJ No.46 Under the Hood)
NT 系でしか使用できず,OS には含まれていない(再配布が必要)
Windows95 系では ToolHelp32 を使用する.(MSJ No.40 Under the Hood)

#include <psapi.h>
#include <tlhelp32.h>
//
// ウィンドウハンドルから EXE 名取得
//
// HWND hWnd           : ウィンドウハンドル
// LPTSTR lpszFileName : フルパスバッファ
// DWORD nSize         : バッファ最大長
//
// return : BOOL : TRUE  : 成功
//                 FALSE : 失敗
//
BOOL GetFNameFromHandled(HWND hWnd, LPTSTR lpszFileName, DWORD nSize)
{
    BOOL bResult = FALSE;
    DWORD dwProcessId;             // プロセス ID
    GetWindowThreadProcessId(hWnd , &dwProcessId);

    // OS 判断
    OSVERSIONINFO osverinfo;
    osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if( !GetVersionEx(&osverinfo) ) {
        return FALSE;
    }

    // Windows NT/2000
    if( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
        // PSAPI 関数のポインタ
        BOOL (WINAPI *lpfEnumProcessModules)
                            (HANDLE, HMODULE*, DWORD, LPDWORD);
        DWORD (WINAPI *lpfGetModuleFileNameEx)
                            (HANDLE, HMODULE, LPTSTR, DWORD);

        // PSAPI.DLL ライブラリをロード
        HINSTANCE hInstLib = LoadLibrary("PSAPI.DLL");
        if( hInstLib == NULL ) {
            return FALSE ;
        }

        // プロシージャのアドレスを取得
        lpfEnumProcessModules = (BOOL(WINAPI *)
            (HANDLE, HMODULE *, DWORD, LPDWORD))GetProcAddress(
                        hInstLib, "EnumProcessModules");
        lpfGetModuleFileNameEx =(DWORD (WINAPI *)
            (HANDLE, HMODULE, LPTSTR, DWORD))GetProcAddress(
                        hInstLib, "GetModuleFileNameExA");

        if( lpfEnumProcessModules && lpfGetModuleFileNameEx ) {
            // プロセスのハンドルを取得
            HANDLE hProcess;
            hProcess = OpenProcess(
                    PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                    FALSE, dwProcessId);
            if( hProcess ) {
                // EXE モジュールのハンドルを取得
                HMODULE hModule;
                DWORD dwNeed;
                if(lpfEnumProcessModules(hProcess, &hModule, sizeof(hModule), &dwNeed) ) {
                    // モジュールハンドルからフルパス名を取得
                    if( lpfGetModuleFileNameEx(hProcess, hModule, lpszFileName, nSize) ) {
                        bResult = TRUE;
                    }
                }
                // プロセスオブジェクトのハンドルをクローズ
                CloseHandle( hProcess ) ;
            }
        }
        // PSAPI.DLL ライブラリを開放
        FreeLibrary( hInstLib ) ;
    }
    // Windows 9x
    else if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) {
        // ToolHelp 関数ポインタ
        HANDLE (WINAPI *lpfCreateSnapshot)(DWORD, DWORD);
        BOOL (WINAPI *lpfProcess32First)(HANDLE, LPPROCESSENTRY32);
        BOOL (WINAPI *lpfProcess32Next)(HANDLE, LPPROCESSENTRY32);

        // プロシージャのアドレスを取得
        lpfCreateSnapshot =
            (HANDLE(WINAPI*)(DWORD,DWORD))GetProcAddress(
                                GetModuleHandle("kernel32.dll"),
                                "CreateToolhelp32Snapshot" );
        lpfProcess32First=
            (BOOL(WINAPI*)(HANDLE,LPPROCESSENTRY32))GetProcAddress(
                                GetModuleHandle("kernel32.dll"),
                                "Process32First" );
        lpfProcess32Next=
            (BOOL(WINAPI*)(HANDLE,LPPROCESSENTRY32))GetProcAddress(
                                GetModuleHandle("kernel32.dll"),
                                "Process32Next" );
        if( !lpfCreateSnapshot
            || !lpfProcess32First
            || !lpfProcess32Next) {
            return FALSE;
        }

        // システム プロセスの Toolhelp スナップショットを作成
        HANDLE hSnapshot;
        hSnapshot = lpfCreateSnapshot(TH32CS_SNAPPROCESS , 0);
        if(hSnapshot != (HANDLE)-1) {
            // 最初のプロセスに関する情報を取得
            PROCESSENTRY32 pe;
            pe.dwSize = sizeof(PROCESSENTRY32);
            if( lpfProcess32First(hSnapshot, &pe) ) {
                do {
                    // 同じプロセスID であれば、ファイル名を取得
                    if(pe.th32ProcessID == dwProcessId) {
                        lstrcpy(lpszFileName, pe.szExeFile);
                        bResult = TRUE;
                        break;
                    }
                } while( lpfProcess32Next(hSnapshot, &pe) );
            }
            // スナップショットを破棄
            CloseHandle(hSnapshot);
        }
    } else {
        return FALSE;
    }

    return bResult;
}


参照
アプリケーションの列挙
前後のTips
PSAPI

DSS ProgrammingTipsCGI Ver2.02