我正在从.Net启动Java进程(“java.exe”)。使用Process.Start()。除了Java进程之外,还会以某种方式启动另一个名为 conhost.exe 的进程。我正在将Java进程的输出重定向到.Net进程。
答案 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;再次下降。
答案 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
进程。