使用c#远程向WinDbg发送命令

本文关键字:命令 WinDbg 使用 | 更新日期: 2023-09-27 17:51:01

在我的应用程序中,WinDbg启动了,我想知道是否有任何方法可以通过WinDbg发送某些命令(例如从c#应用程序发送字母k(以显示调用堆栈)?

我已经阅读了一些使用user32.dll的功能,可以帮助这一点,但我不清楚如何继续并将其包含在我的应用程序。

任何帮助都将是非常感激的。

史蒂夫

使用c#远程向WinDbg发送命令

如果你想完全控制调试引擎,那么你应该使用暴露的COM接口将它托管在你的c#应用程序中。

您可以在WinDbg安装目录中找到自动化调试引擎的示例代码(例如C:'Program Files (x86)'Windows Kits'8.1'Debuggers'x64'sdk'samples)。这篇博客文章展示了如何使用API(在C中)获得堆栈跟踪,因此您不必在发出k命令后解析输出。

最困难的部分是在c#中为所有暴露的对象找到/创建所有的IDebug* [ComImport]接口。但是一旦你有了它们,你可以这样做:

internal static class WinDbgBase
{
    // STDAPI DebugCreate(__in REFIID InterfaceId, __out PVOID* Interface);
    [DllImport("dbgeng.dll", EntryPoint = "DebugCreate", CallingConvention = CallingConvention.StdCall)]
    public static extern int DebugCreate([In] ref System.Guid InterfaceId, ref System.IntPtr Interface);
}
Guid uuidof_IDebugClient4 = new Guid("{ca83c3de-5089-4cf8-93c8-d892387f2a5e}");
IntPtr pObj = IntPtr.Zero;
int hr = WinDbgBase.DebugCreate(ref uuidof_IDebugClient4, ref pObj);
IDebugClient4 _client = (IDebugClient4)Marshal.GetTypedObjectForIUnknown(pObj, typeof(IDebugClient4));
// QueryInterface the other objects
IDebugControl4 _control = (IDebugControl4)_client;
_client.AttachProcess(0, ProcessId, DEBUG_ATTACH.DEBUG_ATTACH_DEFAULT);
_control.WaitForEvent(DEBUG_WAIT.DEBUG_WAIT_DEFAULT, Win32.INFINITE);
...

如果您正在处理托管目标,那么甚至可以加载SOS扩展,获得托管堆栈(如前所述),然后将其与本机堆栈跟踪合并,以便您可以显示包含所有本机到托管转换的完整堆栈。

引用-所有调试器COM对象列表

无需发送按键。有一个更可靠的方法:参见.ocommand的WinDbg帮助。它的工作原理是通过OutputDebugString发送命令,它是。net中的Debug. writeline()(调试构建)或Trace.WriteLine()(发布构建)。

当您自己启动调试器时,您可能希望在启动时立即执行.ocommand,您可以通过添加-c命令行开关来执行:

windbg.exe -p <PID> -c ".ocommand <Magic>;g"

这种方法是一种快捷的方法。@joshpoley的答案是,如果你想要一个长期稳定的解决方案,更清洁的方法。

注意,对于。net,本机调用栈k可能不是你想要的。试试SOS扩展的!clrstack!dumpstack(您可以根据您的。net版本使用.loadby sos clr.loadby sos mscorwks加载)。