启动 Mozilla Firefox 时如何获取进程 ID?

Posted

技术标签:

【中文标题】启动 Mozilla Firefox 时如何获取进程 ID?【英文标题】:How to get the process ID when starting Mozilla Firefox? 【发布时间】:2020-05-25 18:15:29 【问题描述】:

获取我正在启动的进程的 PID 的任务,CreateProcess()ProcessInformation.dwProcessId 在这方面做得很好,但在我的情况下,我启动的进程打开子进程然后关闭,并且我需要获取创建我正在打开的进程的所有 PID。

我找到了这段代码,它接收到子 PID,但它们与最终的 Firefox 窗口不匹配,我做错了什么

来源: CreateProcess returns handle different than launched Chrome.exe

更新 1 在 Drake Wu - MSFT 发表评论后,我使用了以下代码

int test(const wchar_t* programPath) 
    HANDLE Job = CreateJobObject(nullptr, nullptr);
    if (!Job) 
        std::cout << "CreateJobObject, error " << GetLastError() << std::endl;
        return 0;
    

    HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
    if (!IOPort) 
        std::cout << "CreateIoCompletionPort, error " << GetLastError() << std::endl;
        return 0;
    

    JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
    Port.CompletionKey = Job;
    Port.CompletionPort = IOPort;
    if (!SetInformationJobObject(Job,
        JobObjectAssociateCompletionPortInformation,
        &Port, sizeof(Port))) 
        std::cout << "SetInformation, error " << GetLastError() << std::endl;
        return 0;
    

    PROCESS_INFORMATION ProcessInformation;
    STARTUPINFOW StartupInfo =  sizeof(StartupInfo) ;
    LPWSTR szCmdline = const_cast<LPWSTR>(programPath);

    if (!CreateProcessW(
        programPath,
        nullptr,
        nullptr,
        nullptr,
        FALSE,
        CREATE_SUSPENDED,
        nullptr,
        nullptr,
        &StartupInfo,
        &ProcessInformation))
    
        std::cout << "CreateProcess, error " << GetLastError() << std::endl;
        return 0;
    
    std::cout << "PID: " << ProcessInformation.dwProcessId << std::endl;
    if (!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) 
        std::cout << "Assign, error " << GetLastError() << std::endl;
        return 0;
    

    ResumeThread(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hProcess);

    DWORD CompletionCode;
    ULONG_PTR CompletionKey;
    LPOVERLAPPED Overlapped;
    while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
    
        switch (CompletionCode)
        
        case JOB_OBJECT_MSG_NEW_PROCESS:
            std::cout << "New PID: " << (int)Overlapped << std::endl;
            break;
        case JOB_OBJECT_MSG_EXIT_PROCESS:
            std::cout << "Exit PID: " << (int)Overlapped << std::endl;
            break;
        case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
            std::cout << "JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO" << std::endl;
            break;
        default:
            break;
        
        if (CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
            break;
    
    std::cout << "All done" << std::endl;

我得到了以下结果:

standart Firefox

test(L"C:\\Program Files\\Mozilla Firefox\\firefox.exe");

portable edition Firefox

test(L"D:\\FirefoxPortable\\FirefoxPortable.exe");

和以前一样,PID 被错误地返回。在便携版的情况下,进程挂在while循环上,在firefox的标准版的情况下,GetQueuedCompletionStatus()返回JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO。为什么我得到错误的结果?

更新 2

我以管理员身份运行 Visual Studio,但在标准启动时一切正常

【问题讨论】:

请阅读How to Ask。 【参考方案1】:

我测试了Firefox的进程不是新建的,按顺序退出(CreateProcess获取的pid会退出),如果后面有新进程创建,你的代码不会收到新的Firefox进程。

您可以使用swtich-case 语句,以下示例对我有用:

int openProgram(const wchar_t* programPath) 
    HANDLE Job = CreateJobObject(nullptr, nullptr);
    if (!Job) 
        std::cout << "CreateJobObject, error " << GetLastError() << std::endl;
        return 0;
    

    HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
    if (!IOPort) 
        std::cout << "CreateIoCompletionPort, error " << GetLastError() << std::endl;
        return 0;
    

    JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
    Port.CompletionKey = Job;
    Port.CompletionPort = IOPort;
    if (!SetInformationJobObject(Job,
        JobObjectAssociateCompletionPortInformation,
        &Port, sizeof(Port))) 
        std::cout << "SetInformation, error " << GetLastError() << std::endl;
        return 0;
    

    PROCESS_INFORMATION ProcessInformation;
    STARTUPINFO StartupInfo =  sizeof(StartupInfo) ;
    LPTSTR szCmdline = _tcsdup(programPath);
    if (!CreateProcessW(
        nullptr,
        szCmdline,
        nullptr,
        nullptr,
        FALSE,
        CREATE_SUSPENDED,
        nullptr,
        nullptr,
        &StartupInfo,
        &ProcessInformation))
    
        std::cout << "CreateProcess, error " << GetLastError() << std::endl;
        return 0;
    
    std::cout << "PID: " << ProcessInformation.dwProcessId << std::endl;
    if (!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) 
        std::cout << "Assign, error " << GetLastError() << std::endl;
        return 0;
    

    ResumeThread(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hProcess);

    DWORD CompletionCode;
    ULONG_PTR CompletionKey;
    LPOVERLAPPED Overlapped;
    while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
    
        switch (CompletionCode)
        
        case JOB_OBJECT_MSG_NEW_PROCESS:
            std::cout << "New PID: " << (int)Overlapped << std::endl;
            break;
        case JOB_OBJECT_MSG_EXIT_PROCESS:
            std::cout << "Exit PID: " << (int)Overlapped << std::endl;
            break;
        case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
            std::cout << "JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO" << std::endl;
            break;
        default:
            break;
        
        if (CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
            break;
    
    std::cout << "All done" << std::endl;

结果:

【讨论】:

以上是关于启动 Mozilla Firefox 时如何获取进程 ID?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ 启动 Mozilla Firefox?

如何在 Mozilla Firefox 中获取窗口句柄

获取内置 Mozilla Firefox 组件的接口实现

Mozilla启动Firefox品牌重塑,要换新的图标了

当用户在 Mozilla Firefox 上放大和缩小页面时,如何保持 <div> 的大小不变

Firefox 网站如何使其下载统计页面工作?