【问题标题】:c++ how do i get the current console conhost processc++ 如何获取当前的控制台conhost进程
【发布时间】:2016-05-08 05:37:02
【问题描述】:

我在"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 进程...

谢谢! :)

【问题讨论】:

  • 你打算用conhost进程做什么? conhost 进程是一个可能随时更改的实现细节。 (确实,某些版本的 Windows 根本没有主机。)
  • 我将通过WriteProcessMemory 更改SetTextCol 函数,然后将颜色更改为我想要的颜色。 @雷蒙德
  • @CodeAway 你为什么要劫持主机?为什么不能在自己的代码中调用SetConsoleTextAttribute()
  • 我想使用所有RGB colors。 @andlabs
  • @CodeAway that is the question you should have asked instead of this one. 但我看到你已经决定继续走这条路了,祝你好运。 (反正我也不知道答案。)

标签: c++ windows winapi console-application


【解决方案1】:

如果您仍然需要它(在阅读 cmets 之后),这里有一段获取 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控制台应用程序调试 - x86Win 10):

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

Microsoft Windows [Version 10.0.17134.48]

e:\Work\Dev\StackOverflow\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 的子进程(也可以在 ProcExp 中看到)

输出

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

Microsoft Windows [Version 6.1.7601]

c:\Work\Dev\StackOverflow\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...

【讨论】:

  • 在win7上,输出的PPID总是csrss.exe进程的PID,因为它实际上以某种方式拥有它们。
【解决方案2】:

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

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

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

您可能需要通过 Google 搜索才能了解 ProcExp 使用哪些 API 来收集进程开始时间。此外,您可以使用多种工具来查看可执行文件(在本例中为 ProcExp)导入的 API。您可以从 ProcExp 导入的 API 名称中推断出哪些会提供进程的开始时间。

【讨论】:

    【解决方案3】:

    这里有一些令人难以置信的复杂答案。使用进程资源管理器获取控制台应用程序的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,研究 PEB 和 ParameterBlock 的结构,然后您将知道如何获取参数块以及偏移量它在参数块中。您可以在winternl.hhere 中使用_PEB_RTL_USER_PROCESS_PARAMETERS 的类型定义,或者使用ntkrnlmp.pdb 符号编写自己的类型。

    【讨论】:

    • 这是 IOCTL 文件对象(与 DeviceIoControl 一起使用)的句柄,而不是 conhost.exe 的句柄。 pastebin.com/0h7Wn0nj
    • @Martymoose 我会尽快检查这个问题。我不知道,因为我自己正在调查它。我在这里有一些需要编辑的窗口答案
    • @Martymoose 我想你一定是在谈论 windows 10。你能确认它不是 windows 10 上的 conhost 进程的 pid 吗?我有 Windows 7,当然没有 condrv 驱动程序,从我的结果来看,ConsoleHandle 始终是 conhost.exe 进程的 pid
    • 我确实有 win 10。我不知道它在不同版本之间有所不同,很高兴知道。 github.com/microsoft/terminal - 看起来它是开源的,我很惊讶。
    • 这就是我得到的。 ibb.co/5Gtz1Mj
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 2019-10-19
    相关资源
    最近更新 更多