我很感興趣,這將是多麼似是而非捕獲的Win32調試跟蹤全系統的DebugView的方式做。謝天謝地,我對內核消息不感興趣,所以我不需要任何幫助。這需要使用C#,但如果有必要,我很滿意非託管/不安全。在.NET中複製DebugView的功能 - 全局Win32調試掛鉤?
是否有全局鉤子,我可以得到還是我掀起下一個艱辛的道路?
我真的不知道在哪裏的最好的地方是開始這一點。
我很感興趣,這將是多麼似是而非捕獲的Win32調試跟蹤全系統的DebugView的方式做。謝天謝地,我對內核消息不感興趣,所以我不需要任何幫助。這需要使用C#,但如果有必要,我很滿意非託管/不安全。在.NET中複製DebugView的功能 - 全局Win32調試掛鉤?
是否有全局鉤子,我可以得到還是我掀起下一個艱辛的道路?
我真的不知道在哪裏的最好的地方是開始這一點。
我終於到了那裏。它採取了一些嚴重的google搜索,但我發現了一篇文章這有助於...
所有榮譽都歸Chritian Birkl他相當出色的代碼項目DbMon.NET - A simple .NET OutputDebugString capturer。
的代碼非常重要的,但在這裏它是:
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()));
}
}
我會與TraceListener類開始,雖然我不知道這是否可以被用來捕獲Win32的調試跟蹤。
我寫了一個工具,它做的。它不是100%等同於DebugView,但它還有其他一些很好的功能(比如能夠對軌跡着色):-)。
這是可以在這裏找到:TraceSpy
因爲它是100%開源的,它包含了演示如何做到這一點的C#代碼。
+1您抽空分享您的解決方案的麻煩。 – RichieHindle 2009-10-10 22:17:43
你爲什麼打算創建一個SECURITY_DESCRIPTOR?您不要在任何地方將其設置在SECURITY_ATTRIBUTES中。 Attributes結構中的NULL授予與調用進程關聯的默認訪問權限。默認情況下,進程的訪問令牌中的默認DACL只允許訪問訪問令牌所代表的用戶。 http://msdn.microsoft.com/en-us/library/windows/desktop/aa379560(v=vs.85).aspx – Dan 2013-03-31 04:40:57
使用「IntPtr.ToInt64」而不是「IntPtr.ToInt32」會更好嗎用於將4個字節添加到消息字符串中?在64位系統上,32位轉換可能導致溢出。雖然它現在在我的系統上正常工作(使用16 GB中幾乎5個)。 – ygoe 2013-09-03 21:46:40