// This function is used to terminate a process that the SampleEngine launched // The debugger will call IDebugEngineLaunch2::CanTerminateProcess before calling this method. int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 process) { Debug.Assert(_pollThread != null); Debug.Assert(_engineCallback != null); Debug.Assert(_debuggedProcess != null); AD_PROCESS_ID processId = EngineUtils.GetProcessId(process); if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id)) { return(VSConstants.S_FALSE); } try { //_pollThread.RunOperation(() => _debuggedProcess.CmdTerminate()); _debuggedProcess.Terminate(); } catch (ObjectDisposedException) { // Ignore failures caused by the connection already being dead. } Callback.OnProcessExit(0); return(VSConstants.S_OK); }
// This function is used to terminate a process that the engine launched // The debugger will call IDebugEngineLaunch2::CanTerminateProcess before calling this method. int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 process) { Debug.WriteLine("NodeEngine TerminateProcess"); Debug.Assert(_events != null); Debug.Assert(_process != null); int processId = EngineUtils.GetProcessId(process); if (processId != _process.Id) { return(VSConstants.S_FALSE); } EventHandler <AD7EngineEventArgs> detaching = EngineDetaching; if (detaching != null) { detaching(this, new AD7EngineEventArgs(this)); } if (!_pseudoAttach) { _process.Terminate(); } else { _process.Detach(); } return(VSConstants.S_OK); }
// Attach the debug engine to a program. int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason) { Debug.Assert(_ad7ProgramId == Guid.Empty); if (celtPrograms != 1) { Debug.Fail("SampleEngine only expects to see one program in a process"); throw new ArgumentException(); } try { AD_PROCESS_ID processId = EngineUtils.GetProcessId(rgpPrograms[0]); EngineUtils.RequireOk(rgpPrograms[0].GetProgramId(out _ad7ProgramId)); // Attach can either be called to attach to a new process, or to complete an attach // to a launched process if (_pollThread == null) { // We are being asked to debug a process when we currently aren't debugging anything _pollThread = new WorkerThread(); _engineCallback = new EngineCallback(this, ad7Callback); _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError; } else { if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id)) { Debug.Fail("Asked to attach to a process while we are debugging"); return(VSConstants.E_FAIL); } } AD7EngineCreateEvent.Send(this); AD7ProgramCreateEvent.Send(this); this.ProgramCreateEventSent = true; return(VSConstants.S_OK); } catch (MIException e) { return(e.HResult); } catch (Exception e) when(ExceptionHelper.BeforeCatch(e, reportOnlyCorrupting: true)) { return(EngineUtils.UnexpectedException(e)); } }
// Determines if a process can be terminated. int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 process) { Debug.Assert(_events != null); Debug.Assert(_process != null); int processId = EngineUtils.GetProcessId(process); if (processId == _process.Id) { return(VSConstants.S_OK); } return(VSConstants.S_FALSE); }
// Resume a process launched by IDebugEngineLaunch2.LaunchSuspended int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process) { Debug.Assert(_pollThread != null); Debug.Assert(_engineCallback != null); Debug.Assert(_debuggedProcess != null); Debug.Assert(_ad7ProgramId == Guid.Empty); try { AD_PROCESS_ID processId = EngineUtils.GetProcessId(process); if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id)) { return(VSConstants.S_FALSE); } // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach // which will complete the hookup with AD7 IDebugPort2 port; EngineUtils.RequireOk(process.GetPort(out port)); IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port; IDebugPortNotify2 portNotify; EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify)); EngineUtils.RequireOk(portNotify.AddProgramNode(new AD7ProgramNode(_debuggedProcess.Id))); if (_ad7ProgramId == Guid.Empty) { Debug.Fail("Unexpected problem -- IDebugEngine2.Attach wasn't called"); return(VSConstants.E_FAIL); } // NOTE: We wait for the program create event to be continued before we really resume the process return(VSConstants.S_OK); } catch (MIException e) { return(e.HResult); } catch (Exception e) when(ExceptionHelper.BeforeCatch(e, reportOnlyCorrupting: true)) { return(EngineUtils.UnexpectedException(e)); } }
// Determines if a process can be terminated. int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 process) { Debug.Assert(_pollThread != null); Debug.Assert(_engineCallback != null); Debug.Assert(_debuggedProcess != null); AD_PROCESS_ID processId = EngineUtils.GetProcessId(process); if (EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id)) { return(VSConstants.S_OK); } else { return(VSConstants.S_FALSE); } }
// Resume a process launched by IDebugEngineLaunch2.LaunchSuspended int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process) { if (_events == null) { // process failed to start return(VSConstants.E_FAIL); } Debug.Assert(_events != null); Debug.Assert(_process != null); Debug.Assert(_process != null); Debug.Assert(_ad7ProgramId == Guid.Empty); int processId = EngineUtils.GetProcessId(process); if (processId != _process.Id) { Debug.WriteLine("ResumeProcess fails, wrong process"); return(VSConstants.S_FALSE); } // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach // which will complete the hookup with AD7 IDebugPort2 port; EngineUtils.RequireOk(process.GetPort(out port)); var defaultPort = (IDebugDefaultPort2)port; IDebugPortNotify2 portNotify; EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify)); EngineUtils.RequireOk(portNotify.AddProgramNode(new AD7ProgramNode(_process.Id))); if (_ad7ProgramId == Guid.Empty) { Debug.WriteLine("ResumeProcess fails, empty program guid"); Debug.Fail("Unexpected problem -- IDebugEngine2.Attach wasn't called"); return(VSConstants.E_FAIL); } Debug.WriteLine("ResumeProcess return S_OK"); return(VSConstants.S_OK); }
// Attach the debug engine to a program. int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason) { Debug.Assert(_ad7ProgramId == Guid.Empty); if (celtPrograms != 1) { Debug.Fail("Node debugging only supports one program in a process"); throw new ArgumentException(); } IDebugProgram2 program = rgpPrograms[0]; int processId = EngineUtils.GetProcessId(program); if (processId == 0) { // engine only supports system processes Debug.WriteLine("NodeEngine failed to get process id during attach"); return(VSConstants.E_NOTIMPL); } EngineUtils.RequireOk(program.GetProgramId(out _ad7ProgramId)); // Attach can either be called to attach to a new process, or to complete an attach // to a launched process if (_process == null) { // TODO: Where do we get the language version from? _events = ad7Callback; // Check if we're attaching remotely using the node remote debugging transport if (!NodeProcess.TryAttach(processId, out _process)) { MessageBox.Show("Failed to attach debugger:\n", null, MessageBoxButtons.OK, MessageBoxIcon.Error); return(VSConstants.E_FAIL); } AttachProcessEvents(_process); _attached = true; } else { if (processId != _process.Id) { Debug.Fail("Asked to attach to a process while we are debugging"); return(VSConstants.E_FAIL); } } AD7EngineCreateEvent.Send(this); lock (_syncLock) { _programCreated = true; if (_processLoadedThread != null) { SendLoadComplete(_processLoadedThread); } } Debug.WriteLine("NodeEngine Attach returning S_OK"); return(VSConstants.S_OK); }