2009-08-21 25 views
7

Tôi đang khởi chạy một quy trình Java ("java.exe") từ .Net. sử dụng Process.Start(). Ngoài quy trình Java, một quy trình khác được gọi là conhost.exe được khởi chạy bằng cách nào đó. Tôi đang chuyển hướng đầu ra từ tiến trình Java tới tiến trình .Net.Tại sao conhost.exe được khởi chạy?

  1. Tại sao conhost.exe thậm chí được khởi chạy?
  2. Làm cách nào để theo dõi nó từ .Net? Tôi muốn theo dõi trường hợp cụ thể này, và vì tôi không tạo ra nó trực tiếp (nhưng đúng hơn là quá trình Java.exe), tôi không có PID của nó.
+0

không chắc chắn 100% bout có độ chính xác về những gì im sắp nói nhưng từ những gì tôi có thể đọc được conhost actualy lưu trữ dấu nhắc lệnh trong cửa sổ bảy do bắt đầu vào bất kỳ Process.Start() ... tôi tự hỏi tại sao nó ở lại sau khi quá trình này bị giết ... và tại sao địa ngục nó sẽ ngăn chặn u xóa thư mục. cá nhân nếu nó thực sự là vấn đề của bạn tôi sẽ đề nghị làm cho hack và giết chết quá trình bout bạn chắc chắn nên thử mọi thứ khác u có thể trước khi cố gắng (sry cho lỗi chính tả, im frenche làm tốt nhất của tôi để gõ: P) –

+0

Tại sao bạn muốn để theo dõi nó? –

Trả lời

6

Trong các phiên bản trước của Windows, các cửa sổ bảng điều khiển được lưu trữ trong CSRSS, đây là một quá trình quan trọng, đáng tin cậy, có hệ thống. Trên Win7, có vẻ như cửa sổ giao diện điều khiển hiện được lưu trữ trong conhost.exe, có ít quyền hơn. Điều này có thể được thực hiện vì lý do an ninh & độ tin cậy - một vấn đề bảo mật trong hệ thống giao diện điều khiển sẽ không làm hỏng toàn bộ hộp và sự cố trong mã giao diện điều khiển sẽ không hiển thị màu xanh cho hệ thống.

+0

Dưới đây là một số thông tin cơ bản về nó: http://blogs.technet.com/b/askperf/archive/2009/10/05/windows-7-windows-server- 2008-r2-console-host.aspx –

1

Để trắng trợn, tôi không biết gì về Java, vì vậy tôi không thể giúp bạn với # 1. Tôi có thể giúp với # 2, mặc dù.

Để theo dõi nó bằng .NET, bạn có thể sử dụng System.Diagnostics.

Trước tiên, bạn phải lấy từng quy trình bằng tên "conhost.exe", khởi chạy Java, sau đó nhận lại tất cả các quy trình và so sánh.

Để có được các trường hợp cụ thể, sử dụng quá trình ID:

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

Sau đó, khi bạn muốn giết các quá trình, chạy cùng một vòng lặp chính xác, và nếu quá trình ID không được lưu trữ trong các ban đầu vòng lặp, sau đó gọi singleProcess.Kill(); trên đó. Sau đó, bạn sẽ giữ tất cả các quá trình conhost.exe ban đầu còn sống, và chỉ giết những cái được tạo ra giữa thời gian bạn khởi chạy Java trong chương trình của bạn và thời gian tiến trình Java của bạn thoát ra.

+0

Tôi không biết conhost.exe là của tôi, bởi vì tôi không khởi chạy nó trực tiếp, vì vậy tôi không có cách nào để hiểu PID nào là của riêng tôi. – ripper234

+0

Bạn đang sử dụng Windows 7? – Breakthrough

+2

Có. Tôi cũng ghét rằng SO yêu cầu ít nhất 15 ký tự trong các bình luận. – ripper234

3

Cập nhật: I đoán bạn có thể tìm lý do on the oldnewthing. Nó có thể được thêm vào để khôi phục một số chức năng (như kéo và thả) đã bị xóa khỏi Windows Vista vì lý do bảo mật.

Trước khi cập nhật: conhost dường như khởi chạy trên mọi lần mở cmd.exe. Đó có thể là một số điều mới, không có giấy tờ trên các cửa sổ 7.

1

Đây là một quá trình lưu trữ cửa sổ bảng điều khiển. Nó đã được giới thiệu trong Windows 7 (iirc), trong các phiên bản cũ hơn, chức năng này được thực thi trong bối cảnh của quá trình csrss.exe.

+0

Xin lỗi. Tôi đã đăng tải bài đăng của bạn một cách sai lầm ... –

0

Điều này đặt ra một câu hỏi liên quan: bạn có muốn cửa sổ bảng điều khiển cho ứng dụng Java được ứng dụng .NET sinh ra không? Nếu không, bạn có thể thực hiện lệnh javaw thay vì java. Tôi đã không thử nghiệm nó trên Vista, nhưng nó có thể loại bỏ quá trình conhost.exe.

+0

Tôi muốn một cửa sổ giao diện điều khiển vì tôi đang đọc đầu ra của nó từ phía .Net. – ripper234

1

Tôi vừa viết một bài báo cố gắng giải thích mục đích của quá trình. Nó hướng đến những người thường xuyên, nhưng có rất nhiều ảnh chụp màn hình để minh họa.

What is conhost.exe and Why Is It Running?

Điểm mấu chốt là conhost.exe nằm giữa quá trình CSRSS và cmd.exe, vì vậy bạn có thể sử dụng kéo & thả một lần nữa.

alt text

6

Xin lỗi, cho necroing một chủ đề cũ như vậy, nhưng tôi nghĩ rằng vấn đề là thú vị và đáng một câu trả lời.

Tại sao conhost.exe thậm chí được khởi chạy? Như được giải thích trong các bài đăng khác, đây là cách mặc định để lưu trữ các ứng dụng bảng điều khiển. Bạn có thể tìm thêm chi tiết trong bài viết được liên kết trong câu trả lời khác tại đây: What is conhost.exe and Why Is It Running?

Làm cách nào để theo dõi nó từ .Net? Tôi muốn theo dõi trường hợp cụ thể này, và vì tôi không tạo ra nó trực tiếp (nhưng đúng hơn là quá trình Java.exe), tôi không có PID của nó.

Như người khác đã lưu ý rằng có ít lý do để "theo dõi" quá trình conhost. Có nói rằng, có một cách để có được id quá trình conhost từ Id quá trình java.exe của bạn. Tất cả những gì bạn phải làm là liệt kê tất cả quy trình xử lý rằng mọi quá trình conhost trong hệ thống đều có, và nếu một trong các xử lý này trỏ đến một tiến trình có cùng Id với jawa.exe của bạn, thì điều này sẽ là xử lý conhost.exe sau. Covert nó để Process Id và bạn nhận được PID cho conhost.exe

Vì vậy, đây là lý thuyết. Làm thế nào để đạt được điều này trong thực tế? Có một số excellent article hiển thị một số mã đang làm điều gì đó rất giống nhau. Tôi đã sửa đổi mã này một chút cho phù hợp với nhiệm vụ của chúng tôi trong tầm tay. Cuối cùng, bạn có chức năng tĩnh Utility.GetConhostIdByProcessId và chuyển PID của java.exe vào nó, và nó sẽ trả về PID của conhost.exe có liên quan Một cuộc gọi thử nghiệm cho phương thức này có thể được tìm thấy trong hàm Main trong ví dụ dưới đây.

Và bây giờ mã:

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

Lưu ý, rằng tôi chỉ kiểm tra mã này trên x64 Windows 7 với cả hai tùy chọn biên soạn x86 và x64. Tôi biên dịch nó với VS2010 cho .NET 4. Mã này ít hơn có thể đọc được và tôi không thể bảo đảm rằng nó sẽ hoạt động trên tất cả các nền tảng và kiến ​​trúc có liên quan. Tuy nhiên nó hoạt động ở đây (tm) và rất hữu ích cho nhiệm vụ bí truyền này.

+0

Đối với WinXP + thì tốt hơn nên sử dụng SYSTEM_EXTENDED_HANDLE_INFORMATION vì SYSTEM_HANDLE_INFORMATION chỉ trả lại các id quá trình dài 16 bit. Nếu hệ thống được tải nặng bằng các chốt xử lý thì quá trình id-s có xu hướng bắt đầu có các giá trị trên 65k, ví dụ 8 chữ số thập phân. Hệ thống gọi rằng mã trên sử dụng sẽ chỉ đơn giản là che giấu các bit cao của quá trình id-s. Bạn có thể tìm thấy SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX và cách sử dụng nó trong mã nguồn của Process Hacker. Khi tôi nhận được thời gian, tôi sẽ đăng mã C# được cập nhật của riêng mình dựa trên Yours, với một số lỗi logic và rò rỉ cố định. - Cảm ơn rất nhiều vì mã của bạn! –

+0

Vui lòng kiểm tra cập nhật của tôi được thực hiện vào ngày 27/06/2014. Nó liên quan đến việc đóng gói và đọc của UNICODE_STRING struct theo 64-bit, đó là sai cho các mã trên. Vui lòng xem http://stackoverflow.com/a/19871391/193017 –

2

Khi khởi chạy một quá trình bằng cách sử dụng 'Process.Start()', tùy chọn tạo quy trình trực tiếp hoặc khởi chạy 'cmd.exe' và cho phép 'cmd.exe' xử lý các chi tiết. Cờ 'UseShellExecute' kiểm soát điều này. Nếu bạn chọn để lại chi tiết cho 'cmd.exe', điều này thường xảy ra trong các tình huống mà bạn muốn gọi một tệp và để cho trình chạy chạy chương trình thích hợp để xử lý nó, ví dụ: bằng cách "chạy" một tập tin '.txt', sau đó trên Win7 này sẽ thực sự chạy 'cmd', mà chính nó chạy 'conhost'. Nếu, mặt khác, bạn không sử dụng 'ShellExecute' thì 'Start()' sẽ không chạy 'cmd' và bạn sẽ không gián tiếp khởi chạy 'conhost'.

1

Dựa trên zespri's answer Tôi đã viết các phương pháp cập nhật.
Mã này có thể xử lý các id quá trình dài hơn 16 bit.
Cũng có một lỗi logic đã được sửa và một số bộ nhớ và xử lý các rò rỉ. Đã thêm một số lỗi an toàn.
Tôi đã thêm phương thức cho trường hợp conhost.exe có nhiều quy trình được liên kết. Điều này có thể xảy ra khi có một chương trình điều khiển đang chạy và có cmd.exe là quá trình cha mẹ của nó, nhưng cũng có một số trường hợp khác, nơi mà các quy trình liên quan không phải là ngay cả trong mối quan hệ cha-con.
Cảm ơn rất nhiều vì zespri cho mã gốc, có rất nhiều thứ để học hỏi từ nó!

Giải thích thêm về các cập nhật phương pháp:
Đối với WinXP + tốt hơn nên sử dụng SYSTEM_EXTENDED_HANDLE_INFORMATION vì SYSTEM_HANDLE_INFORMATION chỉ trả về các id quá trình dài 16 bit. Nếu hệ thống được tải nặng bằng các chốt xử lý thì quá trình id-s có xu hướng bắt đầu có các giá trị trên 65k, ví dụ 8 chữ số thập phân. Hệ thống gọi rằng mã trên sử dụng sẽ chỉ đơn giản là che giấu các bit cao của quá trình id-s. Bạn có thể tìm thấy SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX và cách sử dụng nó trong mã nguồn của Process Hacker.

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

} 


UPDATE:

tôi đã thêm sửa lỗi quan trọng cho mã 64-bit trên 2014/06/27.
Việc đóng gói cấu trúc UNICODE_STRING là sai và mã đã cố gắng đền bù cho điều đó một cách khéo léo. Mặc dù nó không hiển thị trong Win7, nó đã bị rơi độc đáo dưới Win8.
Đóng gói của các cấu trúc khác với Gói = 1 cũng không chính xác, nhưng vô tình không thay đổi bố cục được tính toán của chúng.
Các bộ phận thay đổi quan trọng là:

[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); 
Các vấn đề liên quan