// constants used in CreateProcess functions /// <summary> /// Creates a new process. /// </summary> /// <param name="commandLine">The commandline to run.</param> /// <param name="commandArguments">The arguments to pass.</param> public void CreateProcess(string commandLine, string commandArguments) { Debug.Assert(!IsAlive); if (IsAlive) throw new InvalidOperationException("cannot call CreateProcess on active process"); var flags = (int) (m_engine.Options.CreateProcessWithNewConsole ? CreateProcessFlags.CREATE_NEW_CONSOLE : 0); try { m_corProcess = m_corDebugger.CreateProcess(commandLine, commandArguments, ".", flags); } catch { CleanAfterProcessExit(); // remove process from process list in case of failure throw; } InitDebuggerCallbacks(); if (commandLine != null) m_name = commandLine; else m_name = commandArguments; }
/// <summary> /// Attach to a process by Process ID (PID) /// </summary> /// <param name="processId">The PID to attach to.</param> public void Attach(int processId) { Debug.Assert(!IsAlive); if (IsAlive) throw new InvalidOperationException("cannot call Attach on active process"); m_processAttaching = true; try { m_corProcess = m_corDebugger.DebugActiveProcess(processId, /*win32Attach*/ false); } catch { // if an attach fails, we need to remove the process object from active processes. CleanAfterProcessExit(); throw; } // User's breakpoint should start with number 0. When launching, 1st breakpoint created is // special -- user entry point and it's given number 0. // In case of attach we don't create any such breakpoint but we still want // to start numbering breakpoints with 1; therefore we'll increase free breakpoint number. if (Breakpoints.m_freeBreakpointNumber == 0) { Breakpoints.m_freeBreakpointNumber = 1; } InitDebuggerCallbacks(); }
// Cleans up the process's resources. This may be called on any thread (including clalback threads). private void CleanAfterProcessExit() { lock (this) { // synchronize with ReallyContinue m_userEntryBreakpoint = null; m_threadMgr.Clear(); m_breakpointMgr.Clear(); m_moduleMgr.Dispose(); if (m_corProcess != null) { m_corProcess.Dispose(); m_corProcess = null; } m_engine.Processes.DeleteProcess(this); } // The SymbolReader interfaces hold a file lock to the pdb file. This lock is held // until the final SymbolReader (including any objects obtained from that SymReader // such as SymDocument, SymMethods) is released. // // We're holding Sym* objects via Com-interop wrappres. So we need to cut all references // and then force a GC to get the Com-wrapper finalizers to run and do the real release. ForceGCCollection(); }