为什么要启动conhost.exe?

时间:2009-08-21 17:18:08

标签: java .net process

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

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

9 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:6)

对不起,对于这个旧帖子的问题,我觉得这个问题很有意思,值得回答。

为什么conhost.exe甚至会启动? 正如其他帖子中所解释的,现在这是托管控制台应用程序的默认方式。有关详细信息,请参阅此处另一个答案中链接的文章:What is conhost.exe and Why Is It Running?

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

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

所以这就是理论。如何在实践中实现这一目标?有一个excellent article显示了一些非常相似的代码。我已经修改了这段代码以适应我们手头的任务。最后你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;
        }
    }
}

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

答案 2 :(得分:3)

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

更新前: conhost似乎在任何cmd.exe开启时启动。它可能是Windows 7上一些新的,未记录的内容。

答案 3 :(得分:2)

当使用'Process.Start()启动进程时,可以选择直接创建进程,或启动'cmd.exe'并让'cmd.exe'处理详细信息。 'UseShellExecute'标志控制着这个。如果您选择将详细信息保留为“cmd.exe”,这在您要调用文件的情况下很常见,并让shell运行相应的程序来处理它,例如通过“运行”'.txt'文件,然后在Win7上,这将实际运行'cmd',它本身运行'conhost'。另一方面,如果你不使用'ShellExecute',那么'Start()'将不会运行'cmd',你也不会间接启动'conhost'。

答案 4 :(得分:1)

要公然,我对Java一无所知,所以我无法帮助你#1。不过,我可以帮助#2。

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

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

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

foreach (Process singleProcess in Process.GetProcessesByName("conhost"))
{
    //Store the following in some kind of array
    somePidArray[yourindex] = singleProcess.Id;
}

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

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

What is conhost.exe and Why Is It Running?

底线是conhost.exe位于CSRSS进程和cmd.exe之间,因此您可以使用drag&amp;再次下降。

alt text

答案 7 :(得分:1)

基于zespri's answer我写了更新的方法。
此代码能够处理长度超过16位的进程ID。
还修复了一个逻辑错误,一些内存和处理泄漏。增加了一些故障安全。
我在conhost.exe有多个关联进程的情况下添加了一个方法。当运行控制台程序并将cmd.exe作为其父进程时,可能会发生这种情况,还有一些其他情况,即关联进程甚至不是子父关系。
非常感谢 zespri 的原始代码,有很多值得学习的东西!

方法更新的更多解释:
对于WinXP +,最好使用SYSTEM_EXTENDED_HANDLE_INFORMATION,因为SYSTEM_HANDLE_INFORMATION只返回16位长的进程id-s。如果系统负载很大,那么进程id-s往往开始具有65k以上的值,例如8个十进制数字。上述代码使用的系统调用将简单地屏蔽进程id-s的高位。您可以在Process Hacker的源代码中找到SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX及其用法。

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
           );
       }
   }

}


更新:

我在27.06.2014上添加了64位代码的重要错误修正。
UNICODE_STRING结构的打包是错误的,代码试图以某种棘手的方式来补偿它。虽然它没有在Win7中体现,但它在Win8下很好地崩溃了。
其他结构'Pack = 1的包装也是不正确的,但是偶然没有改变它们的计算布局。
重要的变化部分是:

[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);

答案 8 :(得分:0)

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