如何获取 conhost.exe 进程号?

How to get conhost.exe process id?

经过一些研究并查看了 ProcessHacker 的源代码,似乎获取 conhost.exe 进程 ID 的方法是使用 NtQuerySystemInformation。

我出于测试目的编写了以下小程序,但它不起作用,我不明白为什么。

{$APPTYPE CONSOLE}

{$TYPEDADDRESS ON}

program _QueryInformationProcess_ProcessConsoleHostProcess;

uses
  Windows,
  sysutils
  ;

{$ifdef VER90}
type
  ptrint  = longint;
  ptruint = DWORD;

const
  DELETE                   = [=11=]010000;
  READ_CONTROL             = [=11=]020000;
  WRITE_DAC                = [=11=]040000;
  WRITE_OWNER              = [=11=]080000;
  SYNCHRONIZE              = [=11=]100000;

  STANDARD_RIGHTS_REQUIRED = [=11=]0F0000;

  STANDARD_RIGHTS_READ     = READ_CONTROL;
  STANDARD_RIGHTS_WRITE    = READ_CONTROL;
  STANDARD_RIGHTS_EXECUTE  = READ_CONTROL;

  STANDARD_RIGHTS_ALL      = [=11=]1F0000;
  SPECIFIC_RIGHTS_ALL      = [=11=]00FFFF;

  PROCESS_ALL_ACCESS        = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $FFF;
{$endif}

const
  ntdll = 'ntdll.dll';

  { process information class(es) used in QueryInformationProcess             }

type
  PROCESSINFOCLASS =
  (
    {  0 }  ProcessBasicInformation,                      // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
    {  1 }  ProcessQuotaLimits,                           // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
    {  2 }  ProcessIoCounters,                            // q: IO_COUNTERS
    {  3 }  ProcessVmCounters,                            // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2
    {  4 }  ProcessTimes,                                 // q: KERNEL_USER_TIMES
    {  5 }  ProcessBasePriority,                          // s: KPRIORITY
    {  6 }  ProcessRaisePriority,                         // s: ULONG
    {  7 }  ProcessDebugPort,                             // q: HANDLE
    {  8 }  ProcessExceptionPort,                         // s: HANDLE
    {  9 }  ProcessAccessToken,                           // s: PROCESS_ACCESS_TOKEN
    { 10 }  ProcessLdtInformation,                        // qs: PROCESS_LDT_INFORMATION                                                               // 10
    { 11 }  ProcessLdtSize,                               // s: PROCESS_LDT_SIZE
    { 12 }  ProcessDefaultHardErrorMode,                  // qs: ULONG
    { 13 }  ProcessIoPortHandlers,                        // (kernel-mode only)
    { 14 }  ProcessPooledUsageAndLimits,                  // q: POOLED_USAGE_AND_LIMITS
    { 15 }  ProcessWorkingSetWatch,                       // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
    { 16 }  ProcessUserModeIOPL,
    { 17 }  ProcessEnableAlignmentFaultFixup,             // s: BOOLEAN
    { 18 }  ProcessPriorityClass,                         // qs: PROCESS_PRIORITY_CLASS
    { 19 }  ProcessWx86Information,
    { 20 }  ProcessHandleCount,                           // q: ULONG, PROCESS_HANDLE_INFORMATION                                                               // 20
    { 21 }  ProcessAffinityMask,                          // s: KAFFINITY
    { 22 }  ProcessPriorityBoost,                         // qs: ULONG
    { 23 }  ProcessDeviceMap,                             // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
    { 24 }  ProcessSessionInformation,                    // q: PROCESS_SESSION_INFORMATION
    { 25 }  ProcessForegroundInformation,                 // s: PROCESS_FOREGROUND_BACKGROUND
    { 26 }  ProcessWow64Information,                      // q: ULONG_PTR
    { 27 }  ProcessImageFileName,                         // q: UNICODE_STRING
    { 28 }  ProcessLUIDDeviceMapsEnabled,                 // q: ULONG
    { 29 }  ProcessBreakOnTermination,                    // qs: ULONG
    { 30 }  ProcessDebugObjectHandle,                     // q: HANDLE                                                               // 30
    { 31 }  ProcessDebugFlags,                            // qs: ULONG
    { 32 }  ProcessHandleTracing,                         // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
    { 33 }  ProcessIoPriority,                            // qs: IO_PRIORITY_HINT
    { 34 }  ProcessExecuteFlags,                          // qs: ULONG
    { 35 }  ProcessResourceManagement,
    { 36 }  ProcessCookie,                                // q: ULONG
    { 37 }  ProcessImageInformation,                      // q: SECTION_IMAGE_INFORMATION
    { 38 }  ProcessCycleTime,                             // q: PROCESS_CYCLE_TIME_INFORMATION                                                               // since VISTA
    { 39 }  ProcessPagePriority,                          // q: ULONG
    { 40 }  ProcessInstrumentationCallback,               // 40
    { 41 }  ProcessThreadStackAllocation,                 // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
    { 42 }  ProcessWorkingSetWatchEx,                     // q: PROCESS_WS_WATCH_INFORMATION_EX[]
    { 43 }  ProcessImageFileNameWin32,                    // q: UNICODE_STRING
    { 44 }  ProcessImageFileMapping,                      // q: HANDLE (input)
    { 45 }  ProcessAffinityUpdateMode,                    // qs: PROCESS_AFFINITY_UPDATE_MODE
    { 46 }  ProcessMemoryAllocationMode,                  // qs: PROCESS_MEMORY_ALLOCATION_MODE
    { 47 }  ProcessGroupInformation,                      // q: USHORT[]
    { 48 }  ProcessTokenVirtualizationEnabled,            // s: ULONG
    { 49 }  ProcessConsoleHostProcess,                    // q: ULONG_PTR
    { 50 }  ProcessWindowInformation,                     // q: PROCESS_WINDOW_INFORMATION                                                               // 50
    { 51 }  ProcessHandleInformation,                     // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION                                                               // since WIN8
    { 52 }  ProcessMitigationPolicy,                      // s: PROCESS_MITIGATION_POLICY_INFORMATION
    { 53 }  ProcessDynamicFunctionTableInformation,
    { 54 }  ProcessHandleCheckingMode,
    { 55 }  ProcessKeepAliveCount,                        // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
    { 56 }  ProcessRevokeFileHandles,                     // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
    { 57 }  ProcessWorkingSetControl,                     // s: PROCESS_WORKING_SET_CONTROL
    { 58 }  ProcessHandleTable,                           // since WINBLUE
    { 59 }  ProcessCheckStackExtentsMode,
    { 60 }  ProcessCommandLineInformation,                // q: UNICODE_STRING                                                               // 60
    { 61 }  ProcessProtectionInformation,                 // q: PS_PROTECTION
    { 62 }  ProcessMemoryExhaustion,                      // PROCESS_MEMORY_EXHAUSTION_INFO                                                               // since THRESHOLD
    { 63 }  ProcessFaultInformation,                      // PROCESS_FAULT_INFORMATION
    { 64 }  ProcessTelemetryIdInformation,                // PROCESS_TELEMETRY_ID_INFORMATION
    { 65 }  ProcessCommitReleaseInformation,              // PROCESS_COMMIT_RELEASE_INFORMATION
    { 66 }  ProcessDefaultCpuSetsInformation,
    { 67 }  ProcessAllowedCpuSetsInformation,
    { 68 }  ProcessReserved1Information,
    { 69 }  ProcessReserved2Information,
    { 70 }  ProcessSubsystemProcess,                      // 70
    { 71 }  ProcessJobMemoryInformation,                  // PROCESS_JOB_MEMORY_INFO
    { 72 }  ProcessInPrivate,                             // since THRESHOLD2
    { 73 }  ProcessRaiseUMExceptionOnInvalidHandleClose,
    { 74 }  MaxProcessInfoClass
  );

type
  NTSTATUS                    = DWORD;

{-----------------------------------------------------------------------------}

function NtQueryInformationProcess(ProcessHandle            : THANDLE;
                                   ProcessInformationClass  : DWORD;
                                   ProcessInformation       : pointer;
                                   ProcessInformationLength : DWORD;
                                   ReturnLength             : PDWORD)
         : NTSTATUS; stdcall; external ntdll;

{-----------------------------------------------------------------------------}

procedure EndProgram(ExitCode : ptruint);
begin
  writeln('Exit code : ', ExitCode);
  writeln('Press <enter>/<return> to end this program.');

  readln;
end;

{-----------------------------------------------------------------------------}

var
  ProcessHandle      : THANDLE;

  ReturnLength       : DWORD;
  NtResult           : NTSTATUS;

  { upon success should contain the conhost.exe process id                    }

  ConsoleHostProcess : ptruint;

begin
  writeln;

  writeln('GetCurrentProcessId : ', GetCurrentProcessId()); { not conhost's   }

  // since we are dealing with our own process we can specify PROCESS_ALL_ACCESS

  ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS,
                               FALSE,
                               GetCurrentProcessId());

  if ProcessHandle = 0 then EndProgram(1);


  // use the process handle to obtain conhost.exe process id

  ReturnLength := 0;  { for good measure }
  NtResult     := 0;

  NtResult := NtQueryInformationProcess(ProcessHandle,
                                        DWORD(ProcessConsoleHostProcess),
                                        @ConsoleHostProcess,
                                        sizeof(ConsoleHostProcess),
                                        nil);
                                        //@ReturnLength);

  { returns 0xC0000003 STATUS_INVALID_INFO_CLASS                              }
  { [Invalid Parameter] The specified information class is not a valid        }
  { information class for the specified object.                               }

  writeln('NTSTATUS           : ', IntToHex(NtResult, 0));
  writeln('ReturnLength       : ', ReturnLength);

  writeln;
  writeln('Press <enter>/<result> to end this program.');
  readln;
end.

如程序评论中所述,我得到 NTSTATUS - 0xC0000003 STATUS_INVALID_INFO_CLASS

这意味着:

[无效参数] 指定的信息 class 不是指定对象的有效信息 class。

但是,我没有看到,我的错误在哪里?

感谢您的帮助。

似乎32位不支持参数ProcessConsoleHostProcess(49),我只能在64位程序中使用它。你可以尝试用 x64 编译它。

document

里面也有提醒

To maintain the compatibility of your application, it is better to use public functions mentioned in the description of the ProcessInformationClass parameter instead.

或者您也可以通过 Tool Help Functions. Here is the related 的其他方式获得它。