Java 为什么要启动conhost.exe?
我正在从.Net启动一个Java进程(“Java.exe”)。使用。除了Java进程外,还以某种方式启动了另一个名为conhost.exe的进程。我正在将Java进程的输出重定向到.Net进程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
坦率地说,我对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);