Java 为什么要启动conhost.exe?

Java 为什么要启动conhost.exe?,java,.net,process,Java,.net,Process,我正在从.Net启动一个Java进程(“Java.exe”)。使用。除了Java进程外,还以某种方式启动了另一个名为conhost.exe的进程。我正在将Java进程的输出重定向到.Net进程 为什么会启动conhost.exe 如何从.Net跟踪它?我想跟踪这个特定的实例,因为我不是直接创建它(而是Java.exe进程),所以我没有它的PID 坦率地说,我对Java一窍不通,所以我无法在#1方面帮助您。不过,我可以帮你做第二件事 要使用.NET跟踪它,可以使用System.Diagnostic

我正在从.Net启动一个Java进程(“Java.exe”)。使用。除了Java进程外,还以某种方式启动了另一个名为conhost.exe的进程。我正在将Java进程的输出重定向到.Net进程

  • 为什么会启动conhost.exe
  • 如何从.Net跟踪它?我想跟踪这个特定的实例,因为我不是直接创建它(而是Java.exe进程),所以我没有它的PID

  • 坦率地说,我对Java一窍不通,所以我无法在#1方面帮助您。不过,我可以帮你做第二件事

    要使用.NET跟踪它,可以使用System.Diagnostics

    首先,您必须以“conhost.exe”的名称获取每个进程,启动Java,然后再次获取所有进程,并进行比较

    要获取特定实例,请使用进程ID:


    然后,当您想要终止进程时,运行完全相同的循环,如果进程ID未存储在初始循环中,则调用singleProcess.kill();在上面。然后,您将保持所有初始conhost.exe进程处于活动状态,并且只杀死在程序中启动Java和Java进程退出之间创建的进程。

    更新:I猜测您可以找到原因。添加它可能是为了恢复由于安全原因从Windows Vista中删除的某些功能(如拖放)


    更新前:conhost似乎在任何cmd.exe打开时启动。它可能是Windows7上一些新的、未记录的东西。

    它是一个托管控制台窗口的进程。它是在Windows 7(iirc)中引入的,在旧版本中,该功能是在csrss.exe进程的上下文中执行的。

    在早期版本的Windows中,控制台窗口托管在csrss中,这是一个高度特权、受信任的系统关键进程。在Win7上,控制台窗口现在似乎托管在conhost.exe中,而conhost.exe具有较少的权限。这可能是出于安全性和可靠性的原因——控制台系统中的安全问题不会影响整个系统,控制台代码中的崩溃也不会使系统蓝屏化。

    这引发了一个相关的问题:是否希望为.NET应用程序生成的Java应用程序提供控制台窗口?如果没有,您可以执行
    javaw
    命令,而不是
    java
    。我没有在Vista上试用过它,但它可能会消除
    conhost.exe
    进程。

    我刚刚写了一篇文章试图解释这个进程的目的。它面向普通人,但有很多截图可以说明

    底线是conhost.exe位于CSRSS进程和cmd.exe之间,因此您可以再次使用拖放


    很抱歉,我删除了这么一条老线索,但我认为这个问题很有趣,值得回答

    为什么会启动conhost.exe? 正如在其他文章中所解释的,这现在是托管控制台应用程序的默认方式。有关更多详细信息,请参阅另一个答案中链接的文章:

    如何从.Net跟踪它?我想跟踪这个特定实例,因为我不是直接创建它(而是Java.exe进程),所以我没有它的PID。

    正如其他人所指出的,应该没有什么理由“跟踪”conhost流程。话虽如此,有一种方法可以从java.exe进程id中获取conhost进程id。您所要做的就是枚举系统中每个conhost进程拥有的所有进程句柄,如果其中一个句柄指向与jawa.exe具有相同id的进程,这将是您要查找的conhost.exe句柄。将其转换为进程Id,即可获得conhost.exe的PID

    这就是理论。如何在实践中实现这一点?有一个例子显示了一些代码正在做一些非常相似的事情。我对这段代码做了一些修改,以适应我们手头的任务。最后,您将
    Utility.GetConhostIdByProcessId
    静态函数,并将java.exe的PID传递给它,它将返回相关conhost.exe的PID。对该方法的测试调用可在下面示例中的主函数中找到

    现在是代码:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    namespace SO1313195
    {
    
        class Program
        {
            static void Main()
            {
                const int processId = 6980;
                int? result = Utility.GetConhostIdByProcessId(processId);
                if (result.HasValue)
                {
                    Console.WriteLine("Process {0} has conhost {1}", processId, result.Value);
                }
                else
                {
                    Console.WriteLine("Unable to find conhost for process {0}", processId);
                }
                Console.ReadLine();
            }
        }
    
        public class Win32Api
        {
            [DllImportAttribute("kernel32.dll", EntryPoint = "GetProcessId")]
            public static extern uint GetProcessId([In]IntPtr process);
    
            [DllImport("ntdll.dll")]
            public static extern int NtQueryObject(IntPtr objectHandle, int
                objectInformationClass, IntPtr objectInformation, int objectInformationLength,
                ref int returnLength);
    
            [DllImport("ntdll.dll")]
            public static extern uint NtQuerySystemInformation(int
                systemInformationClass, IntPtr systemInformation, int systemInformationLength,
                ref int returnLength);
    
            [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
            public static extern void CopyMemory(byte[] destination, IntPtr source, uint length);
    
            [DllImport("kernel32.dll")]
            public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
            [DllImport("kernel32.dll")]
            public static extern int CloseHandle(IntPtr hObject);
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
               ushort hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
               uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
            [DllImport("kernel32.dll")]
            public static extern IntPtr GetCurrentProcess();
    
            public enum ObjectInformationClass
            {
                ObjectBasicInformation = 0,
                ObjectNameInformation = 1,
                ObjectTypeInformation = 2,
                ObjectAllTypesInformation = 3,
                ObjectHandleInformation = 4
            }
    
            [Flags]
            public enum ProcessAccessFlags : uint
            {
                All = 0x001F0FFF,
                Terminate = 0x00000001,
                CreateThread = 0x00000002,
                VmOperation = 0x00000008,
                VmRead = 0x00000010,
                VmWrite = 0x00000020,
                DupHandle = 0x00000040,
                SetInformation = 0x00000200,
                QueryInformation = 0x00000400,
                Synchronize = 0x00100000
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_BASIC_INFORMATION
            {
                public int Attributes;
                public int GrantedAccess;
                public int HandleCount;
                public int PointerCount;
                public int PagedPoolUsage;
                public int NonPagedPoolUsage;
                public int Reserved1;
                public int Reserved2;
                public int Reserved3;
                public int NameInformationLength;
                public int TypeInformationLength;
                public int SecurityDescriptorLength;
                public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_TYPE_INFORMATION
            {
                public UNICODE_STRING Name;
                public int ObjectCount;
                public int HandleCount;
                public int Reserved1;
                public int Reserved2;
                public int Reserved3;
                public int Reserved4;
                public int PeakObjectCount;
                public int PeakHandleCount;
                public int Reserved5;
                public int Reserved6;
                public int Reserved7;
                public int Reserved8;
                public int InvalidAttributes;
                public GENERIC_MAPPING GenericMapping;
                public int ValidAccess;
                public byte Unknown;
                public byte MaintainHandleDatabase;
                public int PoolType;
                public int PagedPoolUsage;
                public int NonPagedPoolUsage;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct UNICODE_STRING
            {
                public ushort Length;
                public ushort MaximumLength;
                public IntPtr Buffer;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct GENERIC_MAPPING
            {
                public int GenericRead;
                public int GenericWrite;
                public int GenericExecute;
                public int GenericAll;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct SYSTEM_HANDLE_INFORMATION
            {
                public int ProcessID;
                public byte ObjectTypeNumber;
                public byte Flags; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                public ushort Handle;
                public int Object_Pointer;
                public UInt32 GrantedAccess;
            }
    
            public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
            public const int DUPLICATE_SAME_ACCESS = 0x2;
        }
    
        class Utility
        {
            public static int? GetConhostIdByProcessId(int processId)
            {
                foreach (Process process in Process.GetProcessesByName("conhost"))
                {
                    IntPtr processHwnd = Win32Api.OpenProcess(Win32Api.ProcessAccessFlags.DupHandle, false, process.Id);
                    List<Win32Api.SYSTEM_HANDLE_INFORMATION> lstHandles = GetHandles(process);
    
                    foreach (Win32Api.SYSTEM_HANDLE_INFORMATION handle in lstHandles)
                    {
                        int? id = GetFileDetails(processHwnd, handle);
                        if (id == processId)
                        {
                            return process.Id;
                        }
                    }
                }
                return null;
            }
    
            private static int? GetFileDetails(IntPtr processHwnd, Win32Api.SYSTEM_HANDLE_INFORMATION systemHandleInformation)
            {
                IntPtr ipHandle;
                Win32Api.OBJECT_BASIC_INFORMATION objBasic = new Win32Api.OBJECT_BASIC_INFORMATION();
                Win32Api.OBJECT_TYPE_INFORMATION objObjectType = new Win32Api.OBJECT_TYPE_INFORMATION();
                int nLength = 0;
    
                if (!Win32Api.DuplicateHandle(processHwnd, systemHandleInformation.Handle, Win32Api.GetCurrentProcess(), out ipHandle, 0, false, Win32Api.DUPLICATE_SAME_ACCESS)) return null;
    
                IntPtr ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
                Win32Api.NtQueryObject(ipHandle, (int)Win32Api.ObjectInformationClass.ObjectBasicInformation, ipBasic, Marshal.SizeOf(objBasic), ref nLength);
                objBasic = (Win32Api.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
                Marshal.FreeHGlobal(ipBasic);
    
    
                IntPtr ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
                nLength = objBasic.TypeInformationLength;
                while ((uint)(Win32Api.NtQueryObject(ipHandle, (int)Win32Api.ObjectInformationClass.ObjectTypeInformation, ipObjectType, nLength, ref nLength)) == Win32Api.STATUS_INFO_LENGTH_MISMATCH)
                {
                    Marshal.FreeHGlobal(ipObjectType);
                    ipObjectType = Marshal.AllocHGlobal(nLength);
                }
    
                objObjectType = (Win32Api.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
                IntPtr ipTemp = Is64Bits() ? new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32) : objObjectType.Name.Buffer;
    
                string strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
                Marshal.FreeHGlobal(ipObjectType);
                if (strObjectTypeName != "Process") return null;
    
                return (int)Win32Api.GetProcessId(ipHandle);
            }
    
            private static List<Win32Api.SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
            {
                const int CNST_SYSTEM_HANDLE_INFORMATION = 16;
                const uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;
    
                int nHandleInfoSize = 0x10000;
                IntPtr ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
                int nLength = 0;
                IntPtr ipHandle;
    
                while ((Win32Api.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer, nHandleInfoSize, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH)
                {
                    nHandleInfoSize = nLength;
                    Marshal.FreeHGlobal(ipHandlePointer);
                    ipHandlePointer = Marshal.AllocHGlobal(nLength);
                }
    
                byte[] baTemp = new byte[nLength];
                Win32Api.CopyMemory(baTemp, ipHandlePointer, (uint)nLength);
    
                long lHandleCount;
                if (Is64Bits())
                {
                    lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                    ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
                }
                else
                {
                    lHandleCount = Marshal.ReadInt32(ipHandlePointer);
                    ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
                }
    
                Win32Api.SYSTEM_HANDLE_INFORMATION shHandle;
                List<Win32Api.SYSTEM_HANDLE_INFORMATION> lstHandles = new List<Win32Api.SYSTEM_HANDLE_INFORMATION>();
    
                for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
                {
                    shHandle = new Win32Api.SYSTEM_HANDLE_INFORMATION();
                    if (Is64Bits())
                    {
                        shHandle = (Win32Api.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                        ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8);
                    }
                    else
                    {
                        ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle));
                        shHandle = (Win32Api.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                    }
                    if (shHandle.ProcessID != process.Id) continue;
                    lstHandles.Add(shHandle);
                }
                return lstHandles;
    
            }
    
            static bool Is64Bits()
            {
                return Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用系统诊断;
    使用System.Runtime.InteropServices;
    名称空间SO1313195
    {
    班级计划
    {
    静态void Main()
    {
    const int processId=6980;
    int?result=Utility.GetConhostIdByProcessId(processId);
    if(result.HasValue)
    {
    WriteLine(“进程{0}有conhost{1}”、进程ID、结果.Value);
    }
    其他的
    {
    WriteLine(“找不到进程{0}的conhost”,processId);
    }
    Console.ReadLine();
    }
    }
    公共类Win32Api
    {
    [DllImportAttribute(“kernel32.dll”,EntryPoint=“GetProcessId”)]
    公共静态外部uint GetProcessId([In]IntPtr进程);
    [DllImport(“ntdll.dll”)]
    公共静态外部int NtQueryObject(IntPtr objectHandle,int
    objectInformationClass、IntPtr objectInformation、int objectInformationLength、,
    ref int返回长度);
    [DllImport(“ntdll.dll”)]
    公共静态外部查询系统信息(int)
    systemInformationClass、IntPtr systemInformation、int systemInformationLength、,
    ref int返回长度);
    [DllImport(“kernel32.dll”,EntryPoint=“rtlmovemory”)]
    公共静态外部无效CopyMemory(字节[]目标,IntPtr源,uint长度);
    [DllImport(“kernel32.dll”)]
    公共静态外部IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess[Marshallas(UnmanagedType.Bool)]Bool bInheritHandle,int dwProcessId);
    [DllImport(“kernel32.dll”)]
    公共静态外部int CloseHandle(IntPtr hObject);
    
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    namespace SO1313195
    {
    
        class Program
        {
            static void Main()
            {
                const int processId = 6980;
                int? result = Utility.GetConhostIdByProcessId(processId);
                if (result.HasValue)
                {
                    Console.WriteLine("Process {0} has conhost {1}", processId, result.Value);
                }
                else
                {
                    Console.WriteLine("Unable to find conhost for process {0}", processId);
                }
                Console.ReadLine();
            }
        }
    
        public class Win32Api
        {
            [DllImportAttribute("kernel32.dll", EntryPoint = "GetProcessId")]
            public static extern uint GetProcessId([In]IntPtr process);
    
            [DllImport("ntdll.dll")]
            public static extern int NtQueryObject(IntPtr objectHandle, int
                objectInformationClass, IntPtr objectInformation, int objectInformationLength,
                ref int returnLength);
    
            [DllImport("ntdll.dll")]
            public static extern uint NtQuerySystemInformation(int
                systemInformationClass, IntPtr systemInformation, int systemInformationLength,
                ref int returnLength);
    
            [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
            public static extern void CopyMemory(byte[] destination, IntPtr source, uint length);
    
            [DllImport("kernel32.dll")]
            public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
            [DllImport("kernel32.dll")]
            public static extern int CloseHandle(IntPtr hObject);
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
               ushort hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
               uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
            [DllImport("kernel32.dll")]
            public static extern IntPtr GetCurrentProcess();
    
            public enum ObjectInformationClass
            {
                ObjectBasicInformation = 0,
                ObjectNameInformation = 1,
                ObjectTypeInformation = 2,
                ObjectAllTypesInformation = 3,
                ObjectHandleInformation = 4
            }
    
            [Flags]
            public enum ProcessAccessFlags : uint
            {
                All = 0x001F0FFF,
                Terminate = 0x00000001,
                CreateThread = 0x00000002,
                VmOperation = 0x00000008,
                VmRead = 0x00000010,
                VmWrite = 0x00000020,
                DupHandle = 0x00000040,
                SetInformation = 0x00000200,
                QueryInformation = 0x00000400,
                Synchronize = 0x00100000
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_BASIC_INFORMATION
            {
                public int Attributes;
                public int GrantedAccess;
                public int HandleCount;
                public int PointerCount;
                public int PagedPoolUsage;
                public int NonPagedPoolUsage;
                public int Reserved1;
                public int Reserved2;
                public int Reserved3;
                public int NameInformationLength;
                public int TypeInformationLength;
                public int SecurityDescriptorLength;
                public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_TYPE_INFORMATION
            {
                public UNICODE_STRING Name;
                public int ObjectCount;
                public int HandleCount;
                public int Reserved1;
                public int Reserved2;
                public int Reserved3;
                public int Reserved4;
                public int PeakObjectCount;
                public int PeakHandleCount;
                public int Reserved5;
                public int Reserved6;
                public int Reserved7;
                public int Reserved8;
                public int InvalidAttributes;
                public GENERIC_MAPPING GenericMapping;
                public int ValidAccess;
                public byte Unknown;
                public byte MaintainHandleDatabase;
                public int PoolType;
                public int PagedPoolUsage;
                public int NonPagedPoolUsage;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct UNICODE_STRING
            {
                public ushort Length;
                public ushort MaximumLength;
                public IntPtr Buffer;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct GENERIC_MAPPING
            {
                public int GenericRead;
                public int GenericWrite;
                public int GenericExecute;
                public int GenericAll;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct SYSTEM_HANDLE_INFORMATION
            {
                public int ProcessID;
                public byte ObjectTypeNumber;
                public byte Flags; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                public ushort Handle;
                public int Object_Pointer;
                public UInt32 GrantedAccess;
            }
    
            public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
            public const int DUPLICATE_SAME_ACCESS = 0x2;
        }
    
        class Utility
        {
            public static int? GetConhostIdByProcessId(int processId)
            {
                foreach (Process process in Process.GetProcessesByName("conhost"))
                {
                    IntPtr processHwnd = Win32Api.OpenProcess(Win32Api.ProcessAccessFlags.DupHandle, false, process.Id);
                    List<Win32Api.SYSTEM_HANDLE_INFORMATION> lstHandles = GetHandles(process);
    
                    foreach (Win32Api.SYSTEM_HANDLE_INFORMATION handle in lstHandles)
                    {
                        int? id = GetFileDetails(processHwnd, handle);
                        if (id == processId)
                        {
                            return process.Id;
                        }
                    }
                }
                return null;
            }
    
            private static int? GetFileDetails(IntPtr processHwnd, Win32Api.SYSTEM_HANDLE_INFORMATION systemHandleInformation)
            {
                IntPtr ipHandle;
                Win32Api.OBJECT_BASIC_INFORMATION objBasic = new Win32Api.OBJECT_BASIC_INFORMATION();
                Win32Api.OBJECT_TYPE_INFORMATION objObjectType = new Win32Api.OBJECT_TYPE_INFORMATION();
                int nLength = 0;
    
                if (!Win32Api.DuplicateHandle(processHwnd, systemHandleInformation.Handle, Win32Api.GetCurrentProcess(), out ipHandle, 0, false, Win32Api.DUPLICATE_SAME_ACCESS)) return null;
    
                IntPtr ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
                Win32Api.NtQueryObject(ipHandle, (int)Win32Api.ObjectInformationClass.ObjectBasicInformation, ipBasic, Marshal.SizeOf(objBasic), ref nLength);
                objBasic = (Win32Api.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
                Marshal.FreeHGlobal(ipBasic);
    
    
                IntPtr ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
                nLength = objBasic.TypeInformationLength;
                while ((uint)(Win32Api.NtQueryObject(ipHandle, (int)Win32Api.ObjectInformationClass.ObjectTypeInformation, ipObjectType, nLength, ref nLength)) == Win32Api.STATUS_INFO_LENGTH_MISMATCH)
                {
                    Marshal.FreeHGlobal(ipObjectType);
                    ipObjectType = Marshal.AllocHGlobal(nLength);
                }
    
                objObjectType = (Win32Api.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
                IntPtr ipTemp = Is64Bits() ? new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32) : objObjectType.Name.Buffer;
    
                string strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
                Marshal.FreeHGlobal(ipObjectType);
                if (strObjectTypeName != "Process") return null;
    
                return (int)Win32Api.GetProcessId(ipHandle);
            }
    
            private static List<Win32Api.SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
            {
                const int CNST_SYSTEM_HANDLE_INFORMATION = 16;
                const uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;
    
                int nHandleInfoSize = 0x10000;
                IntPtr ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
                int nLength = 0;
                IntPtr ipHandle;
    
                while ((Win32Api.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer, nHandleInfoSize, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH)
                {
                    nHandleInfoSize = nLength;
                    Marshal.FreeHGlobal(ipHandlePointer);
                    ipHandlePointer = Marshal.AllocHGlobal(nLength);
                }
    
                byte[] baTemp = new byte[nLength];
                Win32Api.CopyMemory(baTemp, ipHandlePointer, (uint)nLength);
    
                long lHandleCount;
                if (Is64Bits())
                {
                    lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                    ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
                }
                else
                {
                    lHandleCount = Marshal.ReadInt32(ipHandlePointer);
                    ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
                }
    
                Win32Api.SYSTEM_HANDLE_INFORMATION shHandle;
                List<Win32Api.SYSTEM_HANDLE_INFORMATION> lstHandles = new List<Win32Api.SYSTEM_HANDLE_INFORMATION>();
    
                for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
                {
                    shHandle = new Win32Api.SYSTEM_HANDLE_INFORMATION();
                    if (Is64Bits())
                    {
                        shHandle = (Win32Api.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                        ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8);
                    }
                    else
                    {
                        ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle));
                        shHandle = (Win32Api.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                    }
                    if (shHandle.ProcessID != process.Id) continue;
                    lstHandles.Add(shHandle);
                }
                return lstHandles;
    
            }
    
            static bool Is64Bits()
            {
                return Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
            }
        }
    }
    
    void Main()
    {
        //System.Diagnostics.Process.EnterDebugMode();  //TODO: is this necessary?
    
    
        int? ConsoleHost_PId = NativeMethods.GetConhostIdByProcessId(14412376); 
        ConsoleHost_PId.Dump();
    
    
        int pid = 4484;
    
        int? apid = NativeMethods.GetFirstConhostAssociatedProcessId(pid);
        apid.Dump();
    
        var apids = NativeMethods.GetConhostAssociatedProcessIds(pid);
        apids.Dump();   
    }
    
    public static class NativeMethods
    {
       [DllImport("kernel32.dll")]
       public static extern IntPtr GetCurrentProcess();
    
       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern bool CloseHandle(IntPtr hObject);
    
       [DllImportAttribute("kernel32.dll", SetLastError = true)]
       public static extern uint GetProcessId([In]IntPtr process);
    
       [DllImport("ntdll.dll")]
       public static extern uint NtQueryObject(IntPtr objectHandle, 
           int objectInformationClass, IntPtr objectInformation, int objectInformationLength,
           ref int returnLength);
    
       [DllImport("ntdll.dll")]
       public static extern uint NtQuerySystemInformation(int
           systemInformationClass, IntPtr systemInformation, int systemInformationLength,
           ref int returnLength);
    
       [DllImport("kernel32.dll")]
       public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
    
       [DllImport("kernel32.dll", SetLastError = true)]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,  
          IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
          uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
    
       public enum ObjectInformationClass
       {
           ObjectBasicInformation = 0,
           ObjectNameInformation = 1,
           ObjectTypeInformation = 2,
           ObjectAllTypesInformation = 3,
           ObjectHandleInformation = 4
       }
    
       [Flags]
       public enum ProcessAccessFlags : uint
       {
           All = 0x001F0FFF,
           Terminate = 0x00000001,
           CreateThread = 0x00000002,
           VmOperation = 0x00000008,
           VmRead = 0x00000010,
           VmWrite = 0x00000020,
           DupHandle = 0x00000040,
           SetInformation = 0x00000200,
           QueryInformation = 0x00000400,
           Synchronize = 0x00100000
       }
    
       [StructLayout(LayoutKind.Sequential)]
       public struct OBJECT_BASIC_INFORMATION
       {
           public int Attributes;
           public int GrantedAccess;
           public int HandleCount;
           public int PointerCount;
           public int PagedPoolUsage;
           public int NonPagedPoolUsage;
           public int Reserved1;
           public int Reserved2;
           public int Reserved3;
           public int NameInformationLength;
           public int TypeInformationLength;
           public int SecurityDescriptorLength;
           public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
       }
    
       [StructLayout(LayoutKind.Sequential)]
       public struct OBJECT_TYPE_INFORMATION
       {
           public UNICODE_STRING Name;
           public int ObjectCount;
           public int HandleCount;
           public int Reserved1;
           public int Reserved2;
           public int Reserved3;
           public int Reserved4;
           public int PeakObjectCount;
           public int PeakHandleCount;
           public int Reserved5;
           public int Reserved6;
           public int Reserved7;
           public int Reserved8;
           public int InvalidAttributes;
           public GENERIC_MAPPING GenericMapping;
           public int ValidAccess;
           public byte Unknown;
           public byte MaintainHandleDatabase;
           public int PoolType;
           public int PagedPoolUsage;
           public int NonPagedPoolUsage;
       }
    
       [StructLayout(LayoutKind.Sequential)] //, Pack = 1)]  //NB! no packing!
       public struct UNICODE_STRING
       {
           public ushort Length;
           public ushort MaximumLength;
           public IntPtr Buffer;
       }
    
       [StructLayout(LayoutKind.Sequential)]
       public struct GENERIC_MAPPING
       {
           public int GenericRead;
           public int GenericWrite;
           public int GenericExecute;
           public int GenericAll;
       }
    
       [StructLayout(LayoutKind.Sequential)] //, Pack = 1)]  //NB! no packing!
       public struct SYSTEM_HANDLE_INFORMATION
       {
           public ushort UniqueProcessId;
           public ushort CreatorBackTraceIndex;
           public byte ObjectTypeIndex;
           public byte HandleAttributes; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
           public ushort HandleValue;
           public UIntPtr Object;
           public uint GrantedAccess;
       }
    
       //adapted from ProcessExplorer ntexapi.h
       [StructLayout(LayoutKind.Sequential)] //, Pack = 1)]  //NB! no packing!
       public struct SYSTEM_HANDLE_INFORMATION_EX
       {
           public UIntPtr Object;
           public UIntPtr UniqueProcessId;  //changed ulong to IntPtr
           public UIntPtr HandleValue;  //changed ulong to IntPtr
           public uint GrantedAccess;
           public ushort CreatorBackTraceIndex;
           public ushort ObjectTypeIndex;
           public uint HandleAttributes;
           public uint Reserved;
       }
    
       public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
       public const int DUPLICATE_SAME_ACCESS = 0x2;
    
       // ############################################################################
    
       /// <summary>
       /// Some console host processes have multiple associated processes!
       /// </summary>
       public static List<int> GetConhostAssociatedProcessIds(int pid)  
       {
           List<int> result = new List<int>();
    
           IntPtr currentProcess = GetCurrentProcess();
    
           IntPtr processHandle = OpenProcess(ProcessAccessFlags.DupHandle, false, pid);
    
           try
           {
               List<SYSTEM_HANDLE_INFORMATION_EX> lstHandles = GetHandles(pid);
    
               foreach (SYSTEM_HANDLE_INFORMATION_EX handleInformation in lstHandles)
               {
                   int? id = GetFileDetails(processHandle, handleInformation, currentProcess);
    
                   if (id.HasValue)
                       result.Add(id.Value);
               }
    
               return result;
           }
           finally
           {
               CloseHandle(processHandle);
           }
       }
    
       public static int? GetFirstConhostAssociatedProcessId(int pid)  
       {
           IntPtr currentProcess = GetCurrentProcess();
    
           IntPtr processHandle = OpenProcess(ProcessAccessFlags.DupHandle, false, pid);
    
           try 
           {
               List<SYSTEM_HANDLE_INFORMATION_EX> lstHandles = GetHandles(pid);
    
               foreach (SYSTEM_HANDLE_INFORMATION_EX handleInformation in lstHandles)
               {
                   int? id = GetFileDetails(processHandle, handleInformation, currentProcess);
    
                   if (id.HasValue)
                       return id;
               }
    
               return null;
           }
           finally
           {
               CloseHandle(processHandle);
           }
       }
    
       public static int? GetConhostIdByProcessId(int processId)
       {
           IntPtr currentProcess = GetCurrentProcess();
    
           var processes = Process.GetProcessesByName("conhost");
    
           try  
           {
               foreach (Process process in processes)  //TODO: check that this process is really system's console host
               {
                   IntPtr processHandle = OpenProcess(ProcessAccessFlags.DupHandle, false, process.Id);
    
                   try
                   {
    
                       List<SYSTEM_HANDLE_INFORMATION_EX> lstHandles = GetHandles(process.Id);
    
                       foreach (SYSTEM_HANDLE_INFORMATION_EX handleInformation in lstHandles)
                       {
                           int? id = GetFileDetails(processHandle, handleInformation, currentProcess);
    
                           if (id == processId)
                           {
                               return process.Id;
                           }
                       }
                   }
                   finally   
                   {
                       CloseHandle(processHandle);     
                   }
    
               }   //foreach (Process process in Process.GetProcessesByName("conhost"))
    
               return null;
           }
           finally 
           {
               foreach (Process process in processes) 
                   process.Dispose();
           }
    
       }   //public static int? GetConhostIdByProcessId(int processId)
    
       //TODO see this for possible hang under XP 32-bit:
       //http://forum.sysinternals.com/handle-name-help-ntqueryobject_topic14435.html
       //and https://stackoverflow.com/questions/16127948/hang-on-ntquerysysteminformation-in-winxpx32-but-works-fine-in-win7x64
    
       private static int? GetFileDetails(IntPtr processHandle, SYSTEM_HANDLE_INFORMATION_EX systemHandleInformation,
           IntPtr currentProcess)
       {
           IntPtr ipHandle;
           OBJECT_BASIC_INFORMATION objBasic = new OBJECT_BASIC_INFORMATION();
           OBJECT_TYPE_INFORMATION objObjectType = new OBJECT_TYPE_INFORMATION();
           int nLength = 0;
    
           if (Is64Bits())   
           {
               if (!DuplicateHandle(processHandle, new IntPtr(unchecked((long)systemHandleInformation.HandleValue)), currentProcess,
                                           out ipHandle, 0, false, DUPLICATE_SAME_ACCESS))
               {
                   return null;
               }
           }
           else  
           {
               //failsafety
               if ((systemHandleInformation.HandleValue.ToUInt64() >> 32) != 0)
                   return null;
    
               if (!DuplicateHandle(processHandle, new IntPtr(unchecked((int)systemHandleInformation.HandleValue)), currentProcess,
                                           out ipHandle, 0, false, DUPLICATE_SAME_ACCESS))
               {
                   return null;
               }
           }
    
    
           try    
           {
               IntPtr ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
               try
               {
                   NtQueryObject(ipHandle, (int)ObjectInformationClass.ObjectBasicInformation, ipBasic, Marshal.SizeOf(objBasic), ref nLength);
                   objBasic = (OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
               }
               finally
               {
                   Marshal.FreeHGlobal(ipBasic);
               }
    
    
               IntPtr ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
               try
               {
                   nLength = objBasic.TypeInformationLength;
                   while (NtQueryObject(ipHandle, (int)ObjectInformationClass.ObjectTypeInformation, ipObjectType, nLength, ref nLength) == STATUS_INFO_LENGTH_MISMATCH)
                   {
                       Marshal.FreeHGlobal(ipObjectType);
                       ipObjectType = IntPtr.Zero; //zero the pointer before new alloc for case the alloc fails
                       ipObjectType = Marshal.AllocHGlobal(nLength);
                   }
    
                   objObjectType = (OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
                   //IntPtr ipTemp = Is64Bits() ? new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32) : objObjectType.Name.Buffer;
    
                   //string strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
                   string strObjectTypeName = Marshal.PtrToStringUni(objObjectType.Name.Buffer, objObjectType.Name.Length >> 1);
    
    
                   if (strObjectTypeName != "Process")
                       return null;
               }
               finally
               {
                   Marshal.FreeHGlobal(ipObjectType);
               }
    
    
               return (int)GetProcessId(ipHandle);
           }
           finally  
           {
               CloseHandle(ipHandle); 
           }
    
       }   //private static int? GetFileDetails(IntPtr processHandle, SYSTEM_HANDLE_INFORMATION systemHandleInformation, IntPtr currentProcess)
    
       const int CNST_SYSTEM_HANDLE_INFORMATION = 16;
       const int CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64;     //from ProcessHacker ntexapi.h
    
       //http://hintdesk.com/c-get-all-handles-of-a-given-process-in-64-bits/
       private static List<SYSTEM_HANDLE_INFORMATION_EX> GetHandles(int pid)
       {
           List<SYSTEM_HANDLE_INFORMATION_EX> lstHandles = new List<SYSTEM_HANDLE_INFORMATION_EX>();
    
    
           int nHandleInfoSize = 0x10000;
           IntPtr ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
           int nLength = 0;
           IntPtr ipHandle;
    
    
           if (IsWinXP) //from ProcessHacker. This works under Win XP+
           {
               try
               {
                   //the structure array may get larger any number of times during our query
                   while (
                       (
                           NtQuerySystemInformation(CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION, ipHandlePointer,
                                                           nHandleInfoSize, ref nLength)
                       )
                       == STATUS_INFO_LENGTH_MISMATCH
                   )
                   {
                       //TODO: stop loop if buffer size gets large
    
                       nHandleInfoSize = nLength;
                       Marshal.FreeHGlobal(ipHandlePointer);
                       ipHandlePointer = IntPtr.Zero; //zero the pointer before new alloc for case the alloc fails
                       ipHandlePointer = Marshal.AllocHGlobal(nLength);
                   }
    
                   long lHandleCount;
                   if (Is64Bits())     
                   {
                       lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                       ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 16); 
                   }
                   else
                   {
                       lHandleCount = Marshal.ReadInt32(ipHandlePointer); 
                       ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 8);  //changed to 8, tested OK
                   }
    
    
                   SYSTEM_HANDLE_INFORMATION_EX shHandle_ex;
    
                   for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
                   {
                       shHandle_ex = new SYSTEM_HANDLE_INFORMATION_EX();
                       if (Is64Bits())   
                       {
                           shHandle_ex = (SYSTEM_HANDLE_INFORMATION_EX)Marshal.PtrToStructure(ipHandle, shHandle_ex.GetType());   
                           ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle_ex));    
                       }
                       else
                       {
                           shHandle_ex = (SYSTEM_HANDLE_INFORMATION_EX)Marshal.PtrToStructure(ipHandle, shHandle_ex.GetType());    
                           ipHandle = new IntPtr(ipHandle.ToInt32() + Marshal.SizeOf(shHandle_ex));    
                       }
    
                       //failsafety
                       if (shHandle_ex.UniqueProcessId.ToUInt64() > (ulong)int.MaxValue)       //TODO: start using ulong pids?
                           continue;
    
                       if ((int)shHandle_ex.UniqueProcessId.ToUInt32() != pid)  
                           continue;
    
    
                       lstHandles.Add(shHandle_ex);
                   }
    
               }
               finally
               {
                   Marshal.FreeHGlobal(ipHandlePointer);
               }
    
    
               return lstHandles;
    
           }
           else    //if (IsWinXP)
           {
               try
               {
    
                   //the structure array may get larger any number of times during our query
                   while (
                       (
                           NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer,
                                                           nHandleInfoSize, ref nLength)
                       )
                       == STATUS_INFO_LENGTH_MISMATCH
                   )
                   {
                       //TODO: stop loop if buffer size gets large
    
                       nHandleInfoSize = nLength;
                       Marshal.FreeHGlobal(ipHandlePointer);
                       ipHandlePointer = IntPtr.Zero; //zero the pointer before new alloc for case the alloc fails
                       ipHandlePointer = Marshal.AllocHGlobal(nLength);
                   }
    
                   long lHandleCount;
                   if (Is64Bits())   
                   {
                       lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                       ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
                   }
                   else
                   {
                       lHandleCount = Marshal.ReadInt32(ipHandlePointer);
                       ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
                   }
    
    
                   SYSTEM_HANDLE_INFORMATION shHandle;
    
                   for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
                   {
                       shHandle = new SYSTEM_HANDLE_INFORMATION();
                       if (Is64Bits())   
                       {
                           shHandle = (SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());  
                           ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 4);    
                       }
                       else
                       {
                           shHandle = (SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());    
                           ipHandle = new IntPtr(ipHandle.ToInt32() + Marshal.SizeOf(shHandle));    
                       }
    
                       if (shHandle.UniqueProcessId != pid)
                           continue;
    
    
    
                       SYSTEM_HANDLE_INFORMATION_EX shHandle_ex = new SYSTEM_HANDLE_INFORMATION_EX();
    
                       shHandle_ex.Object = shHandle.Object;
                       shHandle_ex.UniqueProcessId = new UIntPtr(shHandle.UniqueProcessId);
                       shHandle_ex.HandleValue = new UIntPtr(shHandle.HandleValue);
                       shHandle_ex.GrantedAccess = shHandle.GrantedAccess;
                       shHandle_ex.CreatorBackTraceIndex = shHandle.CreatorBackTraceIndex;
                       shHandle_ex.ObjectTypeIndex = shHandle.ObjectTypeIndex;
                       shHandle_ex.HandleAttributes = shHandle.HandleAttributes;
    
    
                       lstHandles.Add(shHandle_ex);
                   }
    
               }
               finally
               {
                   Marshal.FreeHGlobal(ipHandlePointer);  
               }
    
    
               return lstHandles;
    
           }    //if (IsWinXP)
    
       }   //private static List<SYSTEM_HANDLE_INFORMATION> GetHandles(int pid)
    
       private static bool Is64Bits()
       {
           return Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
       }
    
       public static bool IsWinXP
       {
           get
           {
               return (
                   false
                   || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)  //WinXP
                   || Environment.OSVersion.Version.Major >= 6  //Vista or 7
               );
           }
       }
    
    }
    
    [StructLayout(LayoutKind.Sequential)] //, Pack = 1)]  //NB! no packing!
    public struct UNICODE_STRING
    
    //IntPtr ipTemp = Is64Bits() ? new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32) : objObjectType.Name.Buffer;
    //string strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
    string strObjectTypeName = Marshal.PtrToStringUni(objObjectType.Name.Buffer, objObjectType.Name.Length >> 1);