为什么要启动conhost.exe?

rip*_*234 7 .net java process

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

  1. 为什么conhost.exe甚至推出?
  2. 如何从.Net跟踪它?我想跟踪这个特定的实例,因为我不是直接创建它(而是Java.exe进程),我没有它的PID.

Mic*_*ael 6

在早期版本的Windows中,控制台窗口托管在CSRSS中,CSRSS是一个高度特权,可信赖的系统关键流程.在Win7上,似乎控制台窗口现在托管在conhost.exe中,conhost.exe具有较少的权限.这可能是出于安全性和可靠性原因而做的 - 控制台系统中的安全问题不会危及整个盒子,并且控制台代码中的崩溃不会蓝屏系统.

  • 以下是有关它的一些背景信息:http://blogs.technet.com/b/askperf/archive/2009/10/05/windows-7-windows-server-2008-r2-console-host.aspx (2认同)

And*_*ykh 6

对不起,为了解决这样一个旧线程,但我认为这个问题很有意思,值得回答.

为什么conhost.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.可以在下面的示例中的Main函数中找到对此方法的测试调用.

现在代码:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我只使用x86和x64编译选项在x64 Windows 7上测试了此代码.我使用VS2010 for .NET 4编译它.这段代码不太可读,我无法保证它可以在所有相关平台和架构上运行.但是它在这里工作(tm)并且对于这个深奥的任务是有用的.