c ++我如何获得当前的控制台conhost进程

c++ how do i get the current console conhost process

我在 "how i get the conhost process" 之后搜索了很多网站,但没有一个是我真正想要的。

我搜索过

我找不到关于 "how to get the conhost process" 的任何信息。

我有一些适用于当前 "cmd.exe / program.exe" 的代码,它给了我 "PID, NAME, PATH, READ/WRITE ADDRESS".

我可以得到 parent 过程,但那不是 conhost.exe

代码"need to link library 'psapi' first":

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
#include <tlhelp32.h>

int PrintModules(DWORD processID) {
    HMODULE hMods[1024];
    HANDLE hProcess;
    DWORD cbNeeded;
    unsigned int i;

    printf( "\nProcess ID: %u\n", processID);

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
    if(NULL == hProcess) return 1;

    if(EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
        for(i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
            TCHAR szModName[MAX_PATH];

            if(GetModuleFileNameEx(hProcess, hMods[i], szModName,sizeof(szModName) / sizeof(TCHAR))) {
                _tprintf( TEXT("  %s (0x%08X)\n"), szModName, hMods[i]);
            }
        }
    }

    CloseHandle(hProcess);

    return 0;
}

int main(void) {
    DWORD cpid = GetCurrentProcessId();
    PrintModules(cpid);

    int ppid = -1;
    HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { 0 };
    pe.dwSize = sizeof(PROCESSENTRY32);
    if(Process32First(h, &pe)) {
        do {
            if(pe.th32ProcessID == cpid) {
                printf("PID: %i; PPID: %i\n", cpid, pe.th32ParentProcessID);
                ppid = pe.th32ParentProcessID;
            }
        } while(Process32Next(h, &pe));
    }
    PrintModules(ppid);
    CloseHandle(h);
    std::cin.get();
    return 0;
}

而且我想不出获取当前 conhost 进程的方法。

当您打开使用控制台的 program 时,会创建一个 conhost.exe 进程。 我的问题是如何获得 conhost.exe 流程...

谢谢! :)

想到的一种方法是获取CMD.EXE进程的开始时间。然后遍历所有 CONHOST 进程,寻找相同(或非常接近)的开始时间。

作为概念验证,下载并安装 Process Explorer。在 ProcExp 中找到您的 CMD.EXE 进程,然后查看“属性”、“图像”选项卡。注意开始时间。然后查看每个 CONHOST 进程,寻找同时启动的进程。

请注意,ProcExp 显示 1 秒的分辨率,但是 API ProcExp 使用的任何底层都可能具有更好的分辨率。

您可能需要 google 了解一些 API(s) ProcExp 使用什么来收集进程启动时间。此外,您还可以使用多种工具来查看 API 可执行文件(在本例中为 ProcExp)导入的内容。您可以从 ProcExp 导入的 API 个名称中推断出哪些名称将提供进程的开始时间。

如果您仍然需要它(阅读评论后),这里有一段代码可以获取 conhost.exe 进程。请注意,我写它只是为了演示目的(检查 [MSDN]: Tool Help Functions 是否可以用于这种情况),所以不要介意它的结构或其他编码 NO-NOs.

code.c:

#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

int main(int argc, char **argv) {
    DWORD pid = 0, i = 0, cPid = 0;
    PROCESSENTRY32 pe32;
    BOOL res = FALSE;
    HANDLE snap = INVALID_HANDLE_VALUE, proc = INVALID_HANDLE_VALUE;
    char c = 0;
    if (argc > 1) {
        pid = atoi(argv[1]);
    } else {
        pid = GetCurrentProcessId();
    }
    printf("PID: %d\n", pid);
    snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
    if (snap == INVALID_HANDLE_VALUE) {
        printf("CreateToolhelp32Snapshot failed: %d\n", GetLastError());
        return -1;
    }
    pe32.dwSize = sizeof(PROCESSENTRY32);
    res = Process32First(snap, &pe32);
    if (res == FALSE) {
        printf("Process32First failed: %d\n", GetLastError());
        CloseHandle(snap);
        return -2;
    }
    do {
        if (_tcscmp(pe32.szExeFile, TEXT("conhost.exe")) == 0) {
            _tprintf(TEXT("    Idx: %02d  PID: %5d  PPID: %5d  Name: %s\n"), i++, pe32.th32ProcessID, pe32.th32ParentProcessID, pe32.szExeFile);
            if (pe32.th32ParentProcessID == pid) {
                cPid = pe32.th32ProcessID;
            }
        }
    } while ((res = Process32Next(snap, &pe32)));
    CloseHandle(snap);

    if ((proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, cPid)) == INVALID_HANDLE_VALUE) {
        printf("OpenProcess failed: %d\n", GetLastError());
        return -3;
    }
    printf("Conhost handle: 0x%08X\n", proc);
    CloseHandle(proc);

    printf("Press a key to exit...\n");
    c = getch();
    return 0;
}

输出(作为 VStudio 2010控制台应用程序调试 - Win 10 上的 x86):

e:\Work\Dev\Whosebug\q035102238>ver

Microsoft Windows [Version 10.0.17134.48]

e:\Work\Dev\Whosebug\q035102238>"Debug\q035102238.exe"
PID: 22388
    Idx: 00  PID: 19892  PPID: 20164  Name: conhost.exe
    Idx: 01  PID: 21128  PPID: 21120  Name: conhost.exe
    Idx: 02  PID:  1144  PPID: 20572  Name: conhost.exe
    Idx: 03  PID:  8184  PPID: 19572  Name: conhost.exe
    Idx: 04  PID: 10976  PPID: 20608  Name: conhost.exe
    Idx: 05  PID: 21284  PPID:  8792  Name: conhost.exe
    Idx: 06  PID:  8172  PPID: 20444  Name: conhost.exe
    Idx: 07  PID:  4396  PPID: 19484  Name: conhost.exe
    Idx: 08  PID: 12484  PPID:  2580  Name: conhost.exe
    Idx: 09  PID: 18636  PPID: 11552  Name: conhost.exe
    Idx: 10  PID: 21456  PPID: 21016  Name: conhost.exe
    Idx: 11  PID:   960  PPID:  3528  Name: conhost.exe
    Idx: 12  PID: 20616  PPID: 18404  Name: conhost.exe
    Idx: 13  PID: 21548  PPID: 21528  Name: conhost.exe
    Idx: 14  PID: 20192  PPID:  8316  Name: conhost.exe
    Idx: 15  PID:  2496  PPID:  9284  Name: conhost.exe
    Idx: 16  PID:  5820  PPID: 23140  Name: conhost.exe
    Idx: 17  PID:  6032  PPID: 26512  Name: conhost.exe
Connhost handle: 0x00000000
Press a key to exit...

所以,可以枚举所有运行conhost.exe个进程,也可以PROCESS_ALL_ACCESS到与我当前关联的进程应用程序(我必须在这里提到我的 Win 用户拥有完全的管理权限)。

@EDIT0:

  • 正如@BladeMight 所注意到的,在 Win 7 all conhost.exe 进程是 crss.exe 的 children(在 ProcExp 中也可以看到)

输出:

c:\Work\Dev\Whosebug\q035102238>ver

Microsoft Windows [Version 6.1.7601]

c:\Work\Dev\Whosebug\q035102238>q035102238.exe
PID: 1548
    Idx: 00  PID:  4960  PPID:  3472  Name: conhost.exe
    Idx: 01  PID:  5024  PPID:  3472  Name: conhost.exe
    Idx: 02  PID:  5076  PPID:  3472  Name: conhost.exe
    Idx: 03  PID:  2676  PPID:  3472  Name: conhost.exe
    Idx: 04  PID:  1888  PPID:  3472  Name: conhost.exe
Connhost handle: 0x00000000
Press a key to exit...

这里有一些令人难以置信的令人费解的答案。使用进程资源管理器获取控制台应用程序的pid,然后在kd -kl

中执行以下操作
lkd> !process 0n16592 0
Searching for Process with Cid == 40d0
Cid handle table at fffff8a001db8000 with 4368 entries in use

PROCESS fffffa8042eb9590
.
.
.
lkd> .process /P fffffa8042eb9590                         
Implicit process is now fffffa80`42eb9590
lkd> !peb                                
PEB at 000007fffffd3000 
.
.
.                                       
    ProcessParameters: 0000000000202880
.
.
.
lkd> dt nt!_RTL_USER_PROCESS_PARAMETERS 0000000000202880
.
.
.
   +0x010 ConsoleHandle    : 0x00000000`00003d98 Void
   +0x018 ConsoleFlags     : 0
   +0x020 StandardInput    : 0x00000000`00000003 Void
   +0x028 StandardOutput   : 0x00000000`00000007 Void
   +0x030 StandardError    : 0x00000000`0000000b Void
.
.
.
.
lkd> ? 0x3d98
Evaluate expression: 15768 = 00000000`00003d98

这是它附加到的 conhost 进程的 pid。在 C++ 中,您必须获取当前的 PEB,看看如何以编程方式完成 here, study the structure of the PEB and ParameterBlock and then you'll know how to get the parameter block and at what offset it is in the parameter block. You can use the type definition for _PEB and _RTL_USER_PROCESS_PARAMETERS in winternl.h or the one here,或者使用 ntkrnlmp.pdb 符号编写您自己的 PEB。