C# 在.NET-全局Win32调试挂钩中复制DebugView的功能?
我感兴趣的是,以DebugView的方式在系统范围内捕获Win32调试跟踪的可能性有多大。谢天谢地,我对内核消息不感兴趣,所以我不需要任何帮助。这需要使用C#,但如果必要,我很乐意使用非托管/不安全 有没有什么全球性的勾当我可以得到,或者我正在走一条艰难的道路C# 在.NET-全局Win32调试挂钩中复制DebugView的功能?,c#,.net,debugging,winapi,C#,.net,Debugging,Winapi,我感兴趣的是,以DebugView的方式在系统范围内捕获Win32调试跟踪的可能性有多大。谢天谢地,我对内核消息不感兴趣,所以我不需要任何帮助。这需要使用C#,但如果必要,我很乐意使用非托管/不安全 有没有什么全球性的勾当我可以得到,或者我正在走一条艰难的道路 我真的不确定从哪里开始这个问题最好。我将从类开始,尽管我不确定是否可以使用它来捕获Win32调试跟踪。我终于做到了。这需要一些认真的谷歌搜索,但我发现一篇文章,这有助于 所有的荣誉都归于克雷蒂安·比克尔,因为他相当出色的代码项目 代码非常
我真的不确定从哪里开始这个问题最好。我将从类开始,尽管我不确定是否可以使用它来捕获Win32调试跟踪。我终于做到了。这需要一些认真的谷歌搜索,但我发现一篇文章,这有助于 所有的荣誉都归于克雷蒂安·比克尔,因为他相当出色的代码项目 代码非常繁重,但这里是:
using System;
using System.Threading;
using System.Runtime.InteropServices;
public delegate void OnOutputDebugStringHandler(int pid, string text);
public sealed class DebugMonitor
{
private DebugMonitor()
{
;
}
#region Win32 API Imports
[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_DESCRIPTOR
{
public byte revision;
public byte size;
public short control;
public IntPtr owner;
public IntPtr group;
public IntPtr sacl;
public IntPtr dacl;
}
[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[Flags]
private enum PageProtection : uint
{
NoAccess = 0x01,
Readonly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
Guard = 0x100,
NoCache = 0x200,
WriteCombine = 0x400,
}
private const int WAIT_OBJECT_0 = 0;
private const uint INFINITE = 0xFFFFFFFF;
private const int ERROR_ALREADY_EXISTS = 183;
private const uint SECURITY_DESCRIPTOR_REVISION = 1;
private const uint SECTION_MAP_READ = 0x0004;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint
dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,
uint dwNumberOfBytesToMap);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool InitializeSecurityDescriptor(ref SECURITY_DESCRIPTOR sd, uint dwRevision);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool SetSecurityDescriptorDacl(ref SECURITY_DESCRIPTOR sd, bool daclPresent, IntPtr dacl, bool daclDefaulted);
[DllImport("kernel32.dll")]
private static extern IntPtr CreateEvent(ref SECURITY_ATTRIBUTES sa, bool bManualReset, bool bInitialState, string lpName);
[DllImport("kernel32.dll")]
private static extern bool PulseEvent(IntPtr hEvent);
[DllImport("kernel32.dll")]
private static extern bool SetEvent(IntPtr hEvent);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFileMapping(IntPtr hFile,
ref SECURITY_ATTRIBUTES lpFileMappingAttributes, PageProtection flProtect, uint dwMaximumSizeHigh,
uint dwMaximumSizeLow, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hHandle);
[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
private static extern Int32 WaitForSingleObject(IntPtr handle, uint milliseconds);
#endregion
public static event OnOutputDebugStringHandler OnOutputDebugString;
private static IntPtr m_AckEvent = IntPtr.Zero;
private static IntPtr m_ReadyEvent = IntPtr.Zero;
private static IntPtr m_SharedFile = IntPtr.Zero;
private static IntPtr m_SharedMem = IntPtr.Zero;
private static Thread m_Capturer = null;
private static object m_SyncRoot = new object();
private static Mutex m_Mutex = null;
public static void Start()
{
lock (m_SyncRoot)
{
if (m_Capturer != null)
throw new ApplicationException("This DebugMonitor is already started.");
if (Environment.OSVersion.ToString().IndexOf("Microsoft") == -1)
throw new NotSupportedException("This DebugMonitor is only supported on Microsoft operating systems.");
bool createdNew = false;
m_Mutex = new Mutex(false, typeof(DebugMonitor).Namespace, out createdNew);
if (!createdNew)
throw new ApplicationException("There is already an instance of 'DbMon.NET' running.");
SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
if (!InitializeSecurityDescriptor(ref sd, SECURITY_DESCRIPTOR_REVISION))
{
throw CreateApplicationException("Failed to initializes the security descriptor.");
}
if (!SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false))
{
throw CreateApplicationException("Failed to initializes the security descriptor");
}
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
m_AckEvent = CreateEvent(ref sa, false, false, "DBWIN_BUFFER_READY");
if (m_AckEvent == IntPtr.Zero)
{
throw CreateApplicationException("Failed to create event 'DBWIN_BUFFER_READY'");
}
m_ReadyEvent = CreateEvent(ref sa, false, false, "DBWIN_DATA_READY");
if (m_ReadyEvent == IntPtr.Zero)
{
throw CreateApplicationException("Failed to create event 'DBWIN_DATA_READY'");
}
m_SharedFile = CreateFileMapping(new IntPtr(-1), ref sa, PageProtection.ReadWrite, 0, 4096, "DBWIN_BUFFER");
if (m_SharedFile == IntPtr.Zero)
{
throw CreateApplicationException("Failed to create a file mapping to slot 'DBWIN_BUFFER'");
}
m_SharedMem = MapViewOfFile(m_SharedFile, SECTION_MAP_READ, 0, 0, 512);
if (m_SharedMem == IntPtr.Zero)
{
throw CreateApplicationException("Failed to create a mapping view for slot 'DBWIN_BUFFER'");
}
m_Capturer = new Thread(new ThreadStart(Capture));
m_Capturer.Start();
}
}
private static void Capture()
{
try
{
IntPtr pString = new IntPtr(
m_SharedMem.ToInt32() + Marshal.SizeOf(typeof(int))
);
while (true)
{
SetEvent(m_AckEvent);
int ret = WaitForSingleObject(m_ReadyEvent, INFINITE);
if (m_Capturer == null)
break;
if (ret == WAIT_OBJECT_0)
{
FireOnOutputDebugString(
Marshal.ReadInt32(m_SharedMem),
Marshal.PtrToStringAnsi(pString));
}
}
}
catch
{
throw;
}
finally
{
Dispose();
}
}
private static void FireOnOutputDebugString(int pid, string text)
{
if (OnOutputDebugString == null)
return;
#if !DEBUG
try
{
#endif
OnOutputDebugString(pid, text);
#if !DEBUG
}
catch (Exception ex)
{
Console.WriteLine("An 'OnOutputDebugString' handler failed to execute: " + ex.ToString());
}
#endif
}
private static void Dispose()
{
if (m_AckEvent != IntPtr.Zero)
{
if (!CloseHandle(m_AckEvent))
{
throw CreateApplicationException("Failed to close handle for 'AckEvent'");
}
m_AckEvent = IntPtr.Zero;
}
if (m_ReadyEvent != IntPtr.Zero)
{
if (!CloseHandle(m_ReadyEvent))
{
throw CreateApplicationException("Failed to close handle for 'ReadyEvent'");
}
m_ReadyEvent = IntPtr.Zero;
}
if (m_SharedFile != IntPtr.Zero)
{
if (!CloseHandle(m_SharedFile))
{
throw CreateApplicationException("Failed to close handle for 'SharedFile'");
}
m_SharedFile = IntPtr.Zero;
}
if (m_SharedMem != IntPtr.Zero)
{
if (!UnmapViewOfFile(m_SharedMem))
{
throw CreateApplicationException("Failed to unmap view for slot 'DBWIN_BUFFER'");
}
m_SharedMem = IntPtr.Zero;
}
if (m_Mutex != null)
{
m_Mutex.Close();
m_Mutex = null;
}
}
public static void Stop()
{
lock (m_SyncRoot)
{
if (m_Capturer == null)
throw new ObjectDisposedException("DebugMonitor", "This DebugMonitor is not running.");
m_Capturer = null;
PulseEvent(m_ReadyEvent);
while (m_AckEvent != IntPtr.Zero)
;
}
}
private static ApplicationException CreateApplicationException(string text)
{
if (text == null || text.Length < 1)
throw new ArgumentNullException("text", "'text' may not be empty or null.");
return new ApplicationException(string.Format("{0}. Last Win32 Error was {1}",
text, Marshal.GetLastWin32Error()));
}
}
使用系统;
使用系统线程;
使用System.Runtime.InteropServices;
公共委托void OnOutputDebugStringHandler(int-pid,字符串文本);
公共密封类调试监视器
{
专用调试监视器()
{
;
}
#区域Win32 API导入
[StructLayout(LayoutKind.Sequential)]
私有结构安全描述符
{
公共字节修改;
公共字节大小;
公共短期控制;
公共IntPtr所有者;
公共IntPtr组;
公共IntPtr sacl;
公共IntPtr dacl;
}
[StructLayout(LayoutKind.Sequential)]
私有结构安全属性
{
公共国际长度;
公共IntPtr lpSecurityDescriptor;
宾利山公共区;
}
[旗帜]
私有枚举页面保护:uint
{
NoAccess=0x01,
只读=0x02,
读写=0x04,
WriteCopy=0x08,
Execute=0x10,
ExecuteRead=0x20,
ExecuteReadWrite=0x40,
ExecuteWriteCopy=0x80,
防护装置=0x100,
NoCache=0x200,
WriteCombine=0x400,
}
私有常量int WAIT_OBJECT_0=0;
私有常量无限=0xFFFFFFFF;
private const int ERROR_已存在=183;
私人建筑安全描述符修订版=1;
专用施工段地图读数=0x0004;
[DllImport(“kernel32.dll”,SetLastError=true)]
私有静态外部IntPtr MapViewOfFile(IntPtr hFileMappingObject,uint
dwDesiredAccess、uint dwFileOffsetHigh、uint dwFileOffsetLow、,
uint dwNumberOfBytesToMap);
[DllImport(“kernel32.dll”,SetLastError=true)]
私有静态外部bool unmpviewoffile(IntPtr lpBaseAddress);
[DllImport(“advapi32.dll”,SetLastError=true)]
私有静态外部布尔初始化安全描述符(参考安全描述符sd,uint dwRevision);
[DllImport(“advapi32.dll”,SetLastError=true)]
私有静态外部bool SetSecurityDescriptorDacl(ref SECURITY_描述符sd,bool daclPresent,IntPtr dacl,bool dacledefaulted);
[DllImport(“kernel32.dll”)]
私有静态外部IntPtr CreateEvent(参考安全属性sa、bool bManualReset、bool bInitialState、字符串lpName);
[DllImport(“kernel32.dll”)]
专用静态外部布尔脉冲事件(IntPtr hEvent);
[DllImport(“kernel32.dll”)]
私有静态外部布尔设置事件(IntPtr hEvent);
[DllImport(“kernel32.dll”,SetLastError=true)]
私有静态外部IntPtr CreateFileMapping(IntPtr hFile,
ref SECURITY_ATTRIBUTES lpFileMappingAttributes、PageProtection flProtect、uint dwMaximumSizeHigh、,
uint dwMaximumSizeLow,字符串lpName);
[DllImport(“kernel32.dll”,SetLastError=true)]
专用静态外部布尔闭合手柄(IntPtr hHandle);
[DllImport(“内核32”,SetLastError=true,ExactSpelling=true)]
私有静态外部Int32 WaitForSingleObject(IntPtr句柄,uint毫秒);
#端区
公共静态事件OnOutputDebugStringHandler OnOutputDebugString;
私有静态IntPtr m_AckEvent=IntPtr.Zero;
私有静态IntPtr m_ReadyEvent=IntPtr.Zero;
私有静态IntPtr m_SharedFile=IntPtr.Zero;
私有静态IntPtr m_SharedMem=IntPtr.Zero;
私有静态线程m_Capturer=null;
私有静态对象m_SyncRoot=新对象();
私有静态互斥m_Mutex=null;
公共静态void Start()
{
锁定(m_SyncRoot)
{
if(m_Capturer!=null)
抛出新的ApplicationException(“此DebugMonitor已启动。”);
if(Environment.OSVersion.ToString().IndexOf(“Microsoft”)=-1)
抛出新的NotSupportedException(“此DebugMonitor仅在Microsoft操作系统上受支持。”);
bool createdNew=false;
m_Mutex=新的互斥(false,typeof(DebugMonitor).Namespace,out createdNew);
如果(!createdNew)
抛出新的ApplicationException(“已经有一个“DbMon.NET”实例正在运行。”);
安全描述符sd=新的安全描述符();
if(!InitializeSecurityDescriptor(参考sd,安全描述符修订版))
{
抛出CreateApplicationException(“未能初始化安全描述符”);
}
if(!SetSecurityDescriptorDacl(参考sd、true、IntPtr.Zero、false))
{
抛出CreateApplicationException(“未能初始化安全描述符”);
}
安全属性sa=新的安全属性();
m_AckEvent=CreateEvent(参考sa,false,false,“DBWIN_BUFFER_READY”);
if(m_AckEvent==IntPtr.Zero)
{
抛出CreateApplicationException(“未能创建事件'DBWIN\u BUFFER\u READY'”;
}
m_ReadyEvent=CreateEvent(参考sa,false,false,“DBWIN_数据准备就绪”);
如果(m_ReadyEvent==IntPtr.Zero)
{
抛出CreateApplicationException(“未能创建事件‘DBWIN_DATA_READY’”);
}
m_SharedFile=CreateFileMapping(新的IntPtr(-1),r