C ++ Win32 - การรับชื่อแอปโดยใช้ PID และ Executable Path

Oct 13 2020

ฉันต้องการทราบชื่อแอปพลิเคชันบน Windows ตอนนี้ฉันกำลังใช้EnumProcesses()เพื่อแจกแจงกระบวนการทั้งหมดและรับรายการ PID

จากนั้นฉันก็วนลูปผ่าน PID ทั้งหมดการวนซ้ำแต่ละครั้งจะมีลักษณะเช่นนี้เมื่อใดaProcess[i]คือ PID ปัจจุบัน:

HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
std::string processName = get_process_name(proc);

get_process_name(proc)ฟังก์ชั่นของฉันใช้GetModuleFileNameExเพื่อรับพา ธ ที่เรียกใช้งานได้และGetProcessImageFileNameเพื่อดึงชื่อของไฟล์ปฏิบัติการ

สิ่งที่ฉันต้องการเรียกโดยทั่วไปคือชื่อแอพตามที่แสดงใน Windows Task Manager

ฉันได้ดูเอกสารของ Win32 API ตลอดและไม่พบเบาะแสเกี่ยวกับวิธีการบรรลุเป้าหมายนี้ ฉันพยายามมองหาวิธีอื่น ๆ เช่นรายการงานของ Windows Shell แต่ให้ผลลัพธ์ที่แตกต่างออกไปตัวอย่างเช่น - Google Chrome:

Image Name: chrome.exe PID: 84 Session Name: Console

ฉันขอขอบคุณทุกความคิดเห็นในเรื่องนี้ไม่ว่าจะเป็น Win32 API หรือวิธีอื่นที่ฉันสามารถใช้งานผ่านโค้ด C ++

คำตอบ

4 ZhuSong-MSFT Oct 13 2020 at 08:46

คุณสามารถทำเช่นนี้กับและGetFileVersionInfoAVerQueryValueA

คุณต้องทำตามตัวอย่างที่ระบุในVerQueryValueAเอกสาร

นี่คือตัวอย่างของฉัน:

struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;

int main()
{
    HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION , FALSE, 2140);   //Modify pid to the pid of your application
    if (!handle) return 0;
    wchar_t pszFile[MAX_PATH] = L"";
    DWORD len = MAX_PATH;
    QueryFullProcessImageName(handle, 0, pszFile, &len);
    UINT dwBytes, cbTranslate;
    DWORD dwSize = GetFileVersionInfoSize(pszFile, (DWORD*)&dwBytes);
    if (dwSize == 0) return 0;
    LPVOID lpData = (LPVOID)malloc(dwSize);
    ZeroMemory(lpData, dwSize);
    if (GetFileVersionInfo(pszFile, 0, dwSize, lpData))
    {
        VerQueryValue(lpData,
            L"\\VarFileInfo\\Translation",
            (LPVOID*)&lpTranslate,
            &cbTranslate);
        wchar_t strSubBlock[MAX_PATH] = { 0 };
        wchar_t* lpBuffer;

        for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
        {
            StringCchPrintf(strSubBlock,50,
                L"\\StringFileInfo\\%04x%04x\\FileDescription",
                lpTranslate[i].wLanguage,
                lpTranslate[i].wCodePage);
            VerQueryValue(lpData,
                strSubBlock,
                (void**)&lpBuffer,
                &dwBytes);
            std::wcout << lpBuffer << std::endl;
        }
    }
    if(lpData) free(lpData);
    if (handle) CloseHandle(handle);
    return 0;
}

และมันได้ผลสำหรับฉัน:

2 yzt Oct 12 2020 at 23:24

ฉันคิดว่าสิ่งที่คุณต้องการคือทรัพยากร "เวอร์ชัน" ที่ฝังอยู่ในไฟล์ PE (ไฟล์ปฏิบัติการ)

ดูเหมือนคุณจะคุ้นเคยกับการใช้ Win32 API ดังนั้นฉันจะให้คำแนะนำแก่คุณ

คุณต้องใช้LoadLibraryExเพื่อโหลดไฟล์ EXE (คำต่อท้าย Ex คือการเปิดใช้งานการส่งLOAD_LIBRARY_AS_DATAFILEแฟล็ก) จากนั้นเรียกEnumResourceTypes(ดูเพิ่มเติมEnumResourceNames) เพื่อระบุประเภททรัพยากร / ทรัพยากรทั้งหมดในไฟล์และค้นหาสิ่งที่คุณกำลังมองหาจากนั้นแยก ข้อมูลด้วยLoadResource. RT_VERSIONชนิดของทรัพยากรที่คุณต้องการคือ

ฉันแน่ใจว่าฉันละเว้นรายละเอียดมากมาย (ตามปกติสำหรับการเขียนโปรแกรม Win32) และอาจไม่จำเป็นต้องมีการแจงนับเลย ในกรณีนี้คุณอาจต้องการโทรFindResourceหรือFindResourceExโดยตรง (หากมีชื่อคงที่สำหรับแหล่งข้อมูลนี้)

ตามคำชี้แจงเพิ่มเติมนี้จะให้วันที่ที่คุณเห็นว่าคุณคลิกขวาที่ไฟล์ EXE (ไม่ใช่ทางลัด) ใน Windows Explorer และเลือก "Properties" จากนั้นไปที่แท็บ "รายละเอียด" หากข้อมูลนั้นเป็นสิ่งที่คุณต้องการจริงๆ (เช่นช่อง "คำอธิบายไฟล์") วิธีการข้างต้นควรให้ข้อมูลแก่คุณ