void DetachProcess() { if (_detached) { return; } if (!DebuggingNativeMethods.DebugActiveProcessStop(_pid)) { _logger.Write("Exception occured when detaching from the process: {0}", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())); } _detached = true; }
private static DEBUG_EVENT?WaitForDebugEvent(uint timeout) { DEBUG_EVENT debugEvent; var success = DebuggingNativeMethods.WaitForDebugEvent(out debugEvent, timeout); if (!success) { int hr = Marshal.GetHRForLastWin32Error(); if (hr == HResults.HR_ERROR_SEM_TIMEOUT) { return(null); } Marshal.ThrowExceptionForHR(hr); } return(debugEvent); }
private void WaitForDebugEvents() { using (var miniDumper = CreateMiniDumper()) { if (_options.NoDumpOptionSelected) { miniDumper.DumpWithoutReason(); DetachProcess(); return; } while (!_detached) { var debugEvent = WaitForDebugEvent(1000); if (_shouldDeatch) { DetachProcess(); return; } if (debugEvent.HasValue) { switch (debugEvent.Value.dwDebugEventCode) { case DEBUG_EVENT_CODE.EXIT_PROCESS_DEBUG_EVENT: if (_options.DumpOnProcessTerminate) { miniDumper.DumpOnProcessExit(debugEvent.Value.ExitProcess.dwExitCode); } _shouldDeatch = true; break; case DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT: var exception = debugEvent.Value.Exception; if (_options.DumpOnException == 1 && exception.dwFirstChance == 1 || _options.DumpOnException == 2 && exception.dwFirstChance == 0) { miniDumper.DumpOnException((uint)debugEvent.Value.dwThreadId, exception.ExceptionRecord); } break; case DEBUG_EVENT_CODE.OUTPUT_DEBUG_STRING_EVENT: if (_options.Verbose) { miniDumper.PrintDebugString(debugEvent.Value.DebugString); } break; default: break; } if (!_shouldDeatch && miniDumper.NumberOfDumpsTaken >= _options.NumberOfDumps) { Console.WriteLine("Number of dumps exceeded the specified limit - detaching."); _shouldDeatch = true; } if (_shouldDeatch) { DetachProcess(); return; } if (_detached) { return; } var continueStatus = HandleDebugEvent(debugEvent.Value); if (!DebuggingNativeMethods.ContinueDebugEvent(debugEvent.Value.dwProcessId, debugEvent.Value.dwThreadId, continueStatus)) { throw new LastWin32ErrorException("Error in ContinueDebugEvent"); } } } } }
void CreateProcess() { bool spawnNew = !string.IsNullOrEmpty(_options.DumpFolderForNewlyStartedProcess); _processName = null; int pid; if (int.TryParse(_options.ProcessInfo, out pid)) { _pid = pid; } else { // not numeric - let's try to find it by name var procs = Process.GetProcesses(); foreach (var proc in procs) { try { if (_options.ProcessInfo.Equals(proc.MainModule.ModuleName, StringComparison.OrdinalIgnoreCase)) { _pid = proc.Id; break; } } catch { // just ignore it } } } if (_pid > 0) { // process found - let's attach to it if (!DebuggingNativeMethods.DebugActiveProcess(_pid)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } _processName = GetProcessName(_pid); return; } if (spawnNew) { // final try - let's try creating it (but only if -x option is set) var commandLine = _options.ProcessInfo + " " + string.Join(" ", _options.Args ?? new string[0]); var startupInfo = new STARTUPINFO(); var processInformation = new PROCESS_INFORMATION(); var processCreationFlags = ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS; if (_options.StartProcessInNewConsoleWindow) { processCreationFlags |= ProcessCreationFlags.CREATE_NEW_CONSOLE; } bool res = ProcessNativeMethods.CreateProcess(null, new StringBuilder(commandLine), null, null, false, processCreationFlags, IntPtr.Zero, null, startupInfo, processInformation); if (!res) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } if (!DebuggingNativeMethods.DebugSetProcessKillOnExit(false)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } _pid = processInformation.dwProcessId; _processName = GetProcessName(_pid); return; } throw new ArgumentException("Something is wrong with the arguments - couldn't find or create a requested process."); }