我需要在满足某些条件时从我的本机C ++程序启动调试器。在C#中我只需要调用System.Diagnostics.Debugger.Launch()。我认为Win32 DebugBreak()调用将执行我想要的操作,但如果没有调试器,它只会终止应用程序。
如何从本机代码启动调试器的新实例(着名的“可能的调试器”对话框)?它甚至可能吗?我可以尝试使用COM来创建Visual Studio的新实例,但它有点复杂,并且还会将我锁定到特定版本的VS.
答案 0 :(得分:11)
我发现可以使用当前进程的PID直接调用vsjitdebugger.exe。确保在工具 - >选项 - >调试 - >在Visual Studio中实时选择“原生”。
这是启动调试器的C ++代码。它使用各种Win32 API的UNICODE版本。我得到System目录,因为CreateProcess()不使用PATH。
bool launchDebugger()
{
// Get System directory, typically c:\windows\system32
std::wstring systemDir(MAX_PATH+1, '\0');
UINT nChars = GetSystemDirectoryW(&systemDir[0], systemDir.length());
if (nChars == 0) return false; // failed to get system directory
systemDir.resize(nChars);
// Get process ID and create the command line
DWORD pid = GetCurrentProcessId();
std::wostringstream s;
s << systemDir << L"\\vsjitdebugger.exe -p " << pid;
std::wstring cmdLine = s.str();
// Start debugger process
STARTUPINFOW si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessW(NULL, &cmdLine[0], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return false;
// Close debugger process handles to eliminate resource leak
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// Wait for the debugger to attach
while (!IsDebuggerPresent()) Sleep(100);
// Stop execution so the debugger can take over
DebugBreak();
return true;
}
答案 1 :(得分:8)
DebugBreak()很好,__ decugbreak()内在函数也是如此。它们都做同样的事情,它们使用STATUS_BREAKPOINT异常使程序崩溃。然后,它会触发Windows错误报告对话框,它会推迟一段时间,然后提供“调试”按钮。然后启动调试器。
你唯一可能犯的错误就是等待WER对话并且按“取消”太快。或禁用WER。如果根本没有可用的调试器,是的,你不能选择一个。
重要的注册表项是HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ AeDebug \ Debugger。通常设置为vsjitdebugger.exe,显示“可能的调试器”对话框。
答案 2 :(得分:0)
从Visual C ++代码中调用_CrtDbgBreak()
,重新编译,运行程序,然后从对话框中选择调试程序。