HardCoded
HardCoded

Reputation: 134

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

i have searched on so many websites after "how i get the conhost process", and nothing is really what i'm looking for.

i have searched on.

and i can't find anything about "how to get the conhost process".

i have some code that works for the current "cmd.exe / program.exe" and that gives me the "PID, NAME, PATH, READ/WRITE ADDRESS".

i can get the parent process but that is not conhost.exe.

code "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;
}

and i can't figure out a way to get the current conhost process.

when you open a program that uses the console, a conhost.exe process is created. and my question is how do i get that conhost.exe process...

Thanks! :)

Upvotes: 4

Views: 3616

Answers (3)

CristiFati
CristiFati

Reputation: 41167

In case you still need it (after reading the comments), here's a piece of code that gets ConHost (conhost.exe) processes. Please note that I only wrote it for demonstrative purposes (to check whether [MS.Learn]: Tool Help Functions can be used for this scenario), so don't mind its structure or other coding NO-NOs.

code00.c:

#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <winternl.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 = NULL;
    char c = 0;
    if (argc > 1) {
        pid = atoi(argv[1]);
    } else {
        pid = GetCurrentProcessId();
    }
    printf("PID: %d\n", pid);
    snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    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 (cPid) {
        if ((proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, cPid)) == NULL) {
            printf("OpenProcess failed: %d\n", GetLastError());
            //return -3;
        } else {
            printf("ConHost handle: 0x%08X\n", proc);
            CloseHandle(proc);
        }
    }

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

So, it is possible to enumerate all running conhost.exe processes, and also get PROCESS_ALL_ACCESS to the one associated with my current application (I have to mention here that my Win user has full administrative privileges)

  • As @BladeMight noticed, on Win 7 all ConHost processes are children of crss.exe (as it can be also seen in ProcExp)

Output:

  • 1st run:

    [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q035102238]> ver
    
    Microsoft Windows [Version 10.0.19045.4355]
    
    [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q035102238]> Debug\q35102238.exe
    PID: 21460
        Idx: 00,  PId: 15004,  PPId:  6636,  Name: conhost.exe
        Idx: 01,  PId:  1996,  PPId: 14992,  Name: conhost.exe
        Idx: 02,  PId:  6964,  PPId:  7908,  Name: conhost.exe
        Idx: 03,  PId:  9620,  PPId:  3168,  Name: conhost.exe
        Idx: 04,  PId: 11828,  PPId:  3040,  Name: conhost.exe
        Idx: 05,  PId: 15832,  PPId: 15732,  Name: conhost.exe
        Idx: 06,  PId:  3276,  PPId: 11808,  Name: conhost.exe
        Idx: 07,  PId: 17336,  PPId: 17316,  Name: conhost.exe
        Idx: 08,  PId: 16284,  PPId: 15020,  Name: conhost.exe
        Idx: 09,  PId: 16908,  PPId: 16760,  Name: conhost.exe
        Idx: 10,  PId: 11220,  PPId:  5224,  Name: conhost.exe
        Idx: 11,  PId: 11832,  PPId: 15764,  Name: conhost.exe
        Idx: 12,  PId: 17460,  PPId: 17440,  Name: conhost.exe
        Idx: 13,  PId: 17808,  PPId: 17788,  Name: conhost.exe
        Idx: 14,  PId: 18216,  PPId: 18196,  Name: conhost.exe
        Idx: 15,  PId: 15736,  PPId:  3724,  Name: conhost.exe
        Idx: 16,  PId: 17852,  PPId: 17900,  Name: conhost.exe
        Idx: 17,  PId: 13068,  PPId:  6908,  Name: conhost.exe
        Idx: 18,  PId: 14116,  PPId: 12172,  Name: conhost.exe
        Idx: 19,  PId:  1564,  PPId: 10668,  Name: conhost.exe
        Idx: 20,  PId:  9592,  PPId:  9612,  Name: conhost.exe
        Idx: 21,  PId:  1364,  PPId:  9848,  Name: conhost.exe
        Idx: 22,  PId:  7040,  PPId: 16308,  Name: conhost.exe
        Idx: 23,  PId: 15484,  PPId: 22092,  Name: conhost.exe
        Idx: 24,  PId: 18996,  PPId:  2668,  Name: conhost.exe
        Idx: 25,  PId: 11108,  PPId: 19440,  Name: conhost.exe
        Idx: 26,  PId:  4792,  PPId: 25404,  Name: conhost.exe
        Idx: 27,  PId: 14948,  PPId: 20596,  Name: conhost.exe
    Press a key to exit...
    
  • Processes layout:

    Img00

  • 2nd run - passing 2668 (parent Cmd PId):

    [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q035102238]> Debug\q35102238.exe 2668
    PID: 2668
        Idx: 00,  PId: 15004,  PPId:  6636,  Name: conhost.exe
        Idx: 01,  PId:  1996,  PPId: 14992,  Name: conhost.exe
        Idx: 02,  PId:  6964,  PPId:  7908,  Name: conhost.exe
        Idx: 03,  PId:  9620,  PPId:  3168,  Name: conhost.exe
        Idx: 04,  PId: 11828,  PPId:  3040,  Name: conhost.exe
        Idx: 05,  PId: 15832,  PPId: 15732,  Name: conhost.exe
        Idx: 06,  PId:  3276,  PPId: 11808,  Name: conhost.exe
        Idx: 07,  PId: 17336,  PPId: 17316,  Name: conhost.exe
        Idx: 08,  PId: 16284,  PPId: 15020,  Name: conhost.exe
        Idx: 09,  PId: 16908,  PPId: 16760,  Name: conhost.exe
        Idx: 10,  PId: 11220,  PPId:  5224,  Name: conhost.exe
        Idx: 11,  PId: 11832,  PPId: 15764,  Name: conhost.exe
        Idx: 12,  PId: 17460,  PPId: 17440,  Name: conhost.exe
        Idx: 13,  PId: 17808,  PPId: 17788,  Name: conhost.exe
        Idx: 14,  PId: 18216,  PPId: 18196,  Name: conhost.exe
        Idx: 15,  PId: 15736,  PPId:  3724,  Name: conhost.exe
        Idx: 16,  PId: 17852,  PPId: 17900,  Name: conhost.exe
        Idx: 17,  PId: 13068,  PPId:  6908,  Name: conhost.exe
        Idx: 18,  PId: 14116,  PPId: 12172,  Name: conhost.exe
        Idx: 19,  PId:  1564,  PPId: 10668,  Name: conhost.exe
        Idx: 20,  PId:  9592,  PPId:  9612,  Name: conhost.exe
        Idx: 21,  PId:  1364,  PPId:  9848,  Name: conhost.exe
        Idx: 22,  PId:  7040,  PPId: 16308,  Name: conhost.exe
        Idx: 23,  PId: 15484,  PPId: 22092,  Name: conhost.exe
        Idx: 24,  PId: 18996,  PPId:  2668,  Name: conhost.exe
        Idx: 25,  PId: 11108,  PPId: 19440,  Name: conhost.exe
        Idx: 26,  PId:  4792,  PPId: 25404,  Name: conhost.exe
        Idx: 27,  PId: 14948,  PPId: 20596,  Name: conhost.exe
        Idx: 28,  PId: 23172,  PPId: 15672,  Name: conhost.exe
        Idx: 29,  PId: 23516,  PPId: 13352,  Name: conhost.exe
    ConHost handle: 0x000000DC
    Press a key to exit...
    

Upvotes: 2

Lewis Kelsey
Lewis Kelsey

Reputation: 4697

Some unbelievably convoluted answers here. Use process explorer to get the pid of the console application and then do the following in 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

This is the pid of the conhost process that it is attached to. In C++, you'd have to get the current PEB, take a look at how that is done programmatically 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, or write your own using the ntkrnlmp.pdb symbols.

Upvotes: -1

Χpẘ
Χpẘ

Reputation: 3451

One method that comes to mind is to obtain the start time of the CMD.EXE process. Then iterate through all of the CONHOST processes looking for the same (or very close) start time.

As a proof of concept download and install Process Explorer. Find your CMD.EXE process in ProcExp, then look at Properties, Image tab. Note the start time. Then look through each CONHOST process looking for one that starts at the same time.

Note that ProcExp displays 1 second resolution, but whatever underlying API ProcExp uses probably has better resolution.

You may need to google some to get an idea what API(s) ProcExp uses to gather the process start time. Additionally there are a variety of tools you can use to see what APIs an executable (ProcExp in this case) import. You may be able to deduce from the API names that ProcExp imports which one(s) would provide a process' start time.

Upvotes: 2

Related Questions