public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = null; if (ProcessId.ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM) { return VSConstants.E_FAIL; } IEnumDebugProcesses2 processEnum; int hr = EnumProcesses(out processEnum); if (ErrorHandler.Failed(hr)) { return hr; } var processes = new IDebugProcess2[1]; var pids = new AD_PROCESS_ID[1]; uint fetched = 0; while (true) { hr = processEnum.Next(1, processes, ref fetched); if (ErrorHandler.Failed(hr)) { return hr; } else if (fetched == 0) { return VSConstants.E_FAIL; } if (ErrorHandler.Succeeded(processes[0].GetPhysicalProcessId(pids)) && ProcessId.dwProcessId == pids[0].dwProcessId) { ppProcess = processes[0]; return VSConstants.S_OK; } } }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { if (!(debugEvent is IDebugProcessCreateEvent2) && !(debugEvent is IDebugProcessDestroyEvent2)) return VSConstants.S_OK; var target = GetTargetFromProcess(process); if (target == null) { _package.Reporter.ReportWarning("Can't find target from process {0} ({1}). Event: {2}.", process.GetName(), process.GetProcessId(), TypeHelper.GetDebugEventTypeName(debugEvent)); return VSConstants.S_OK; } if (debugEvent is IDebugProcessCreateEvent2) { target.IsAttached = true; _package.History.Items.AddFirst(target); _package.Ui.Update(); } else { target.IsAttached = false; _package.Ui.Update(); } return VSConstants.S_OK; }
public static int Event(this IDebugEventCallback2 callback, IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, DebugEvent debugEvent) { Contract.Requires<ArgumentNullException>(callback != null, "callback"); Contract.Requires<ArgumentNullException>(debugEvent != null, "debugEvent"); Contract.Requires<ArgumentNullException>(engine != null, "engine"); return callback.Event(engine, process, program, thread, debugEvent, debugEvent.EventGuid, (uint)debugEvent.Attributes); }
public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = null; if (ProcessId.ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM) { return VSConstants.E_FAIL; } ppProcess = GetProcesses().FirstOrDefault(p => p.ProcessId == ProcessId.dwProcessId); return ppProcess != null ? VSConstants.S_OK : VSConstants.E_FAIL; }
public static int GetProcessId(IDebugProcess2 process) { AD_PROCESS_ID[] pid = new AD_PROCESS_ID[1]; EngineUtils.RequireOk(process.GetPhysicalProcessId(pid)); if (pid[0].ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM) { return 0; } return (int)pid[0].dwProcessId; }
/// <summary> /// Perform actual send /// </summary> private void Send(IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, BaseEvent @event) { var guid = @event.IID; DLog.Debug(DContext.VSDebuggerEvent, "DebugEngine Event {0} {1}", @event.GetType().Name, guid); var rc = callback.Event(engine, process, program, thread, @event, ref guid, (uint)@event.Attributes); if (!ErrorHandler.Succeeded(rc)) { DLog.Error(DContext.VSDebuggerEvent, "DebugEngine Event failed {0}", rc); } }
public int Event(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { if (pEvent is IRunspaceRequest) { var request = pEvent as IRunspaceRequest; request.SetRunspace(_runspace, _breakpoints); } return VSConstants.S_OK; }
public int Event( IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { Logger.Debug( string.Empty ); return VSConstants.S_OK; }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { if (process == null) return VSConstants.S_OK; string processName; if (process.GetName((uint) enum_GETNAME_TYPE.GN_FILENAME, out processName) != VSConstants.S_OK) return VSConstants.S_OK; if (processName.EndsWith("vshost.exe")) return VSConstants.S_OK; var shortName = Path.GetFileName(processName); if (debugEvent is IDebugProcessCreateEvent2) { Log.Instance.SetStatus("[attaching...] {0}", shortName); Storage.Instance.SubscribeProcess(processName); } if (debugEvent is IDebugProcessDestroyEvent2) { Log.Instance.SetStatus("[detached] {0}", shortName); Log.Instance.AppendLine("[detached] {0}", shortName); } if (debugEvent is IDebugLoadCompleteEvent2) { if (program != null) { string engineName; Guid engineId; if (program.GetEngineInfo(out engineName, out engineId) == VSConstants.S_OK) { var fields = new PROCESS_INFO[1]; if (process.GetInfo((uint)enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID, fields) != VSConstants.S_OK) return VSConstants.S_OK; Storage.Instance.SubscribeEngine(processName, engineId); AttachCenter.Instance.Freeze(); Log.Instance.SetStatus("[attached] {0}", shortName); Log.Instance.AppendLine("[attached] {0} ({1}) / {2}", shortName, fields[0].ProcessId.dwProcessId, engineName); } } } return VSConstants.S_OK; }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { // Ignore a few events right away. if (debugEvent is IDebugModuleLoadEvent2 || debugEvent is IDebugThreadCreateEvent2 || debugEvent is IDebugThreadDestroyEvent2) return VSConstants.S_OK; if (process == null) return VSConstants.S_OK; if (debugEvent is IDebugProcessCreateEvent2) { State.IsAttached = true; } else if (debugEvent is IDebugProcessDestroyEvent2) { State.IsAttached = false; } return VSConstants.S_OK; }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { // Ignore a few events right away. if (debugEvent is IDebugModuleLoadEvent2 || debugEvent is IDebugThreadCreateEvent2 || debugEvent is IDebugThreadDestroyEvent2) return VSConstants.S_OK; // Trace.WriteLine(TypeHelper.GetDebugEventTypeName(debugEvent)); // TODO: Remove me. if (process == null) return VSConstants.S_OK; var target = GetTargetFromProcess(process); if (target == null) { _package.Reporter.ReportWarning("Can't find target from process {0} ({1}). Event: {2}.", process.GetName(), process.GetProcessId(), TypeHelper.GetDebugEventTypeName(debugEvent)); return VSConstants.S_OK; } if (debugEvent is IDebugProcessCreateEvent2) { target.IsAttached = true; _package.History.Items.AddFirst(target); _package.Ui.Update(); return VSConstants.S_OK; } if (debugEvent is IDebugProcessDestroyEvent2) { target.IsAttached = false; _package.Ui.Update(); return VSConstants.S_OK; } return VSConstants.S_OK; }
public int Event(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { if (riidEvent == typeof(IDebugOutputStringEvent2).GUID) { IDebugOutputStringEvent2 ev = pEvent as IDebugOutputStringEvent2; if (ev != null) { string message; if (ErrorHandler.Succeeded(ev.GetString(out message))) { var lines = message.Split(sp, StringSplitOptions.RemoveEmptyEntries); foreach(var line in lines) { HandleMessage(line); } } } } return VSConstants.S_OK; }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { // _package.Reporter.ReportTrace(TypeHelper.GetDebugEventTypeName(debugEvent)); if (!(debugEvent is IDebugProcessCreateEvent2) && !(debugEvent is IDebugProcessDestroyEvent2)) return VSConstants.S_OK; var target = GetTargetFromProcess(process); if (target == null) { _package.Reporter.ReportWarning("Can't find target from process {0} ({1}). Event: {2}.", process.GetName(), process.GetProcessId(), TypeHelper.GetDebugEventTypeName(debugEvent)); return VSConstants.S_OK; } if (debugEvent is IDebugProcessCreateEvent2) { var engines = target.Engines.Where(e => _engines.ContainsKey(e)).Select(e => _engines[e]).ToArray(); var mode = new DBGMODE[1]; _debugger.GetMode(mode); if (mode[0] == DBGMODE.DBGMODE_Design) return VSConstants.S_OK; target.IsAttached = true; _package.History.Items.AddFirst(target); _package.Ui.Update(); } else { target.IsAttached = false; _package.Ui.Update(); } return VSConstants.S_OK; }
public int Event(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { if (riidEvent == typeof(IDebugProgramCreateEvent2).GUID) { Guid processId; // A program was created and attached if (pProcess != null) { if (VSConstants.S_OK == pProcess.GetProcessId(out processId)) { DkmProcess dkmProcess = DkmProcess.FindProcess(processId); if (dkmProcess != null) { var debugTrigger = DkmExceptionCodeTrigger.Create(DkmExceptionProcessingStage.Thrown, null, DkmExceptionCategory.Win32, RemoteDebugStartExceptionCode); var attachTrigger = DkmExceptionCodeTrigger.Create(DkmExceptionProcessingStage.Thrown, null, DkmExceptionCategory.Win32, RemoteDebugAttachExceptionCode); // Try to add exception trigger for when a remote debugger server is started for Python dkmProcess.AddExceptionTrigger(RemoteDebugExceptionGuid, debugTrigger); dkmProcess.AddExceptionTrigger(RemoteDebugExceptionGuid, attachTrigger); } } } } return VSConstants.S_OK; }
public int Event(IDebugEngine2 engine, IDebugProcess2 process, IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2 debugEvent, ref Guid riidEvent, uint attributes) { bool savedProgram = false; bool savedThread = false; if (riidEvent == processCreateEvent) { AD_PROCESS_ID[] pdwProcessId = new AD_PROCESS_ID[1]; process.GetPhysicalProcessId(pdwProcessId); Debug.Assert(!this.attachedProcesses.Contains(pdwProcessId[0].dwProcessId)); this.attachedProcesses.Add(pdwProcessId[0].dwProcessId); } else if (riidEvent == processDestroyEvent) { AD_PROCESS_ID[] pdwProcessId = new AD_PROCESS_ID[1]; process.GetPhysicalProcessId(pdwProcessId); Debug.Assert(this.attachedProcesses.Contains(pdwProcessId[0].dwProcessId)); this.attachedProcesses.Remove(pdwProcessId[0].dwProcessId); } else if (riidEvent == breakInEvent && this.currentDebugProgram != program && program != null && thread != null) { // Evaluate an expression get access to the memory context and the bitness. IDebugProperty2 debugProperty = this.EvaluateExpression(thread, "(void**)0x0 + 1"); if (debugProperty != null) { using (new DisposableComReference(debugProperty)) { DEBUG_PROPERTY_INFO[] debugPropertyInfo = new DEBUG_PROPERTY_INFO[1]; if (debugProperty.GetPropertyInfo((uint)enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE, 16, evaluateExpressionTimeout, null, 0, debugPropertyInfo) == S_OK) { IDebugMemoryContext2 memoryContext = null; IDebugMemoryBytes2 memoryBytes = null; if (debugProperty.GetMemoryContext(out memoryContext) == S_OK && debugProperty.GetMemoryBytes(out memoryBytes) == S_OK) { DisposableComReference.SetReference(ref this.currentDebugProgram, program); DisposableComReference.SetReference(ref this.currentThread, thread); DisposableComReference.SetReference(ref this.memoryContext, memoryContext); DisposableComReference.SetReference(ref this.memoryBytes, memoryBytes); ulong offset = ulong.Parse(debugPropertyInfo[0].bstrValue.Substring("0x".Length), System.Globalization.NumberStyles.AllowHexSpecifier); // Adjust the memory context and calculate the bitness. this.memoryContext.Subtract(offset, out memoryContext); DisposableComReference.SetReference(ref this.memoryContext, memoryContext); this.isPointer64Bit = (offset == 8); this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.Detaching); this.engine.DiaLoader.ClearSymbols(); savedProgram = true; savedThread = true; } else { DisposableComReference.ReleaseIfNotNull(ref memoryContext); DisposableComReference.ReleaseIfNotNull(ref memoryBytes); } } } } } else if (riidEvent == stopDebugEvent) { // The debugger stopped. Clear the references. DisposableComReference.ReleaseIfNotNull(ref this.currentDebugProgram); DisposableComReference.ReleaseIfNotNull(ref this.memoryContext); DisposableComReference.ReleaseIfNotNull(ref this.memoryBytes); this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.Detaching); this.engine.DiaLoader.ClearSymbols(); } else if (riidEvent == breakInEvent) { // The debugger broke in, notify the client. this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.Break); } else if (riidEvent == threadSwitchEvent) { // The user switched the current thread. DisposableComReference.SetReference(ref this.currentThread, thread); savedThread = true; if (this.currentThread != null) { uint threadId; thread.GetThreadId(out threadId); this.TargetThreadSystemId = threadId; } bool processChanged = false; if (process != null) { AD_PROCESS_ID[] pdwProcessId = new AD_PROCESS_ID[1]; process.GetPhysicalProcessId(pdwProcessId); if (this.TargetProcessSystemId != 0) { if (pdwProcessId[0].dwProcessId != this.TargetProcessSystemId) { this.TargetProcessSystemId = pdwProcessId[0].dwProcessId; processChanged = true; } } else { this.TargetProcessSystemId = pdwProcessId[0].dwProcessId; if (this.TargetProcessSystemId != 0) { processChanged = true; } } } else if (this.TargetProcessSystemId != 0) { this.TargetProcessSystemId = 0; processChanged = true; } if (processChanged) { DisposableComReference.SetReference(ref this.currentDebugProgram, program); savedProgram = true; if (program != null) { // Evaluate an expression get access to the memory context and the bitness. IDebugProperty2 debugProperty = this.EvaluateExpression(thread, "(void**)0x0 + 1"); if (debugProperty != null) { using (new DisposableComReference(debugProperty)) { DEBUG_PROPERTY_INFO[] debugPropertyInfo = new DEBUG_PROPERTY_INFO[1]; if (debugProperty.GetPropertyInfo((uint)enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE, 16, evaluateExpressionTimeout, null, 0, debugPropertyInfo) == S_OK) { IDebugMemoryContext2 memoryContext = null; IDebugMemoryBytes2 memoryBytes = null; if ((debugProperty.GetMemoryContext(out memoryContext) == S_OK) && (debugProperty.GetMemoryBytes(out memoryBytes) == S_OK)) { DisposableComReference.SetReference(ref this.memoryContext, memoryContext); DisposableComReference.SetReference(ref this.memoryBytes, memoryBytes); ulong offset = ulong.Parse(debugPropertyInfo[0].bstrValue.Substring("0x".Length), System.Globalization.NumberStyles.AllowHexSpecifier); // Adjust the memory context and calculate the bitness. this.memoryContext.Subtract(offset, out memoryContext); DisposableComReference.SetReference(ref this.memoryContext, memoryContext); this.isPointer64Bit = (offset == 8); } else { DisposableComReference.ReleaseIfNotNull(ref memoryContext); DisposableComReference.ReleaseIfNotNull(ref memoryBytes); } } } } this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.ChangingProcess); } } else { this.engine.NotifyDebuggerStatusChange(DebuggerChangeEventArgs.DebuggerStatus.ChangingThread); } } if (!savedProgram) { DisposableComReference.ReleaseIfNotNull(ref program); } if (!savedThread) { DisposableComReference.ReleaseIfNotNull(ref thread); } DisposableComReference.ReleaseIfNotNull(ref engine); DisposableComReference.ReleaseIfNotNull(ref process); DisposableComReference.ReleaseIfNotNull(ref debugEvent); return S_OK; }
int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 pProcess) { ThrowIfDisposed(); return(VSConstants.S_OK); }
/// <summary> /// Gets the containing process. /// </summary> public int GetProcess(out IDebugProcess2 ppProcess) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugProgram2.GetProcess"); ppProcess = process; return(VSConstants.S_OK); }
public ILldbAttachedProgram Create( IDebugProcess2 debugProcess, Guid programId, IDebugEngine2 debugEngine, IDebugEventCallback2 callback, SbDebugger debugger, RemoteTarget target, LldbListenerSubscriber listenerSubscriber, SbProcess process, SbCommandInterpreter commandInterpreter, bool isCoreAttach, IExceptionManager exceptionManager, IModuleSearchLogHolder moduleSearchLogHolder, uint remotePid) { // Required due to an issue triggered by the proxy used to wrap debugProgramFactory. // TODO: Remove assertion once the issue with Castle.DynamicProxy is // fixed. _taskContext.ThrowIfNotOnMainThread(); var debugEngineHandler = _debugEngineHandlerFactory.Create(debugEngine, callback); var binaryLoader = _binaryLoaderFactory.Create(target); var symbolLoader = _symbolLoaderFactory.Create(commandInterpreter); var moduleFileLoader = _moduleFileLoaderFactory.Create(symbolLoader, binaryLoader, moduleSearchLogHolder); var debugModuleCache = _debugModuleCacheFactory.Create( (lldbModule, loadOrder, ggpProgram) => _debugModuleFactory.Create( moduleFileLoader, moduleSearchLogHolder, lldbModule, loadOrder, debugEngineHandler, ggpProgram)); var ad7FrameInfoCreator = new AD7FrameInfoCreator(debugModuleCache); var stackFrameCreator = new StackFramesProvider.StackFrameCreator( (frame, thread, program) => _debugStackFrameCreator( ad7FrameInfoCreator, frame, thread, debugEngineHandler, program)); var threadCreator = new DebugProgram.ThreadCreator( (thread, program) => _debugThreadCreatorDelegate( ad7FrameInfoCreator, stackFrameCreator, thread, program)); var debugProgram = _debugProgramFactory.Create( debugEngineHandler, threadCreator, debugProcess, programId, process, target, debugModuleCache, isCoreAttach); _taskExecutor.StartAsyncTasks( ex => debugEngineHandler.Abort(debugProgram, ExitInfo.Error(ex))); var breakpointManager = _breakpointManagerFactory.Create(debugEngineHandler, debugProgram); var eventManager = _eventManagerFactory.Create(debugEngineHandler, breakpointManager, debugProgram, process, listenerSubscriber); // TODO: Listen for module load/unload events from LLDB binaryLoader.LldbModuleReplaced += (o, args) => { debugModuleCache.GetOrCreate(args.AddedModule, debugProgram); debugModuleCache.Remove(args.RemovedModule); }; debugModuleCache.ModuleAdded += (o, args) => debugEngineHandler.OnModuleLoad(args.Module, debugProgram); debugModuleCache.ModuleRemoved += (o, args) => debugEngineHandler.OnModuleUnload(args.Module, debugProgram); return(new LldbAttachedProgram(breakpointManager, eventManager, _lldbShell, moduleFileLoader, debugEngineHandler, _taskExecutor, debugProgram, debugger, target, process, exceptionManager, debugModuleCache, listenerSubscriber, remotePid)); }
public int GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { throw new NotImplementedException(); }
// 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 Constants.S_OK; } else { return Constants.S_FALSE; } }
public int GetProcess(out IDebugProcess2 process) { Debug.Fail("This function is not called by the debugger"); process = null; return(VSConstants.S_OK); }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(m_ad7ProgramId == Guid.Empty); m_ad7ProgramId = Guid.NewGuid(); STARTUPINFO si = new STARTUPINFO(); pi = new PROCESS_INFORMATION(); // try/finally free bool procOK = NativeMethods.CreateProcess(exe, args, IntPtr.Zero, IntPtr.Zero, false, ProcessCreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi); pID = pi.dwProcessId; Task writepipeOK = WriteNamedPipeAsync(); Task readpipeOK = ReadNamedPipeAsync(); threadHandle = pi.hThread; IntPtr processHandle = pi.hProcess; // Inject LuaDebug into host IntPtr loadLibAddr = DLLInjector.GetProcAddress(DLLInjector.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); string VS140ExtensionPath = Path.Combine(Path.GetDirectoryName(typeof(EngineConstants).Assembly.Location), "LuaDetour"); string luaDetoursDllName = Path.Combine(VS140ExtensionPath, "LuaDetours.dll"); if (!File.Exists(luaDetoursDllName)) { process = null; return(VSConstants.E_FAIL); } IntPtr allocMemAddress1 = DLLInjector.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)((luaDetoursDllName.Length + 1) * Marshal.SizeOf(typeof(char))), DLLInjector.MEM_COMMIT | DLLInjector.MEM_RESERVE, DLLInjector.PAGE_READWRITE); UIntPtr bytesWritten1; DLLInjector.WriteProcessMemory(processHandle, allocMemAddress1, Encoding.Default.GetBytes(luaDetoursDllName), (uint)((luaDetoursDllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten1); IntPtr hRemoteThread1 = DLLInjector.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibAddr, allocMemAddress1, 0, IntPtr.Zero); IntPtr[] handles1 = new IntPtr[] { hRemoteThread1 }; uint index1; NativeMethods.CoWaitForMultipleHandles(0, -1, handles1.Length, handles1, out index1); string debugDllName = Path.Combine(VS140ExtensionPath, "LuaDebug32.dll"); IntPtr allocMemAddress2 = DLLInjector.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)((debugDllName.Length + 1) * Marshal.SizeOf(typeof(char))), DLLInjector.MEM_COMMIT | DLLInjector.MEM_RESERVE, DLLInjector.PAGE_READWRITE); UIntPtr bytesWritten2; DLLInjector.WriteProcessMemory(processHandle, allocMemAddress2, Encoding.Default.GetBytes(debugDllName), (uint)((debugDllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten2); IntPtr hRemoteThread2 = DLLInjector.CreateRemoteThread(processHandle, IntPtr.Zero, 0, loadLibAddr, allocMemAddress2, 0, IntPtr.Zero); IntPtr[] handles = new IntPtr[] { hRemoteThread2 }; uint index2; NativeMethods.CoWaitForMultipleHandles(0, -1, handles.Length, handles, out index2); AD_PROCESS_ID adProcessId = new AD_PROCESS_ID(); adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = pi.dwProcessId; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); debugProcess = process; return(VSConstants.S_OK); }
int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { ppProcess = null; return(VSConstants.E_NOTIMPL); }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(_pollThread == null); Debug.Assert(_engineCallback == null); Debug.Assert(_debuggedProcess == null); Debug.Assert(_ad7ProgramId == Guid.Empty); // Check if the logger was enabled late. Logger.LoadMIDebugLogger(_configStore); process = null; _engineCallback = new EngineCallback(this, ad7Callback); Exception exception; try { bool noDebug = launchFlags.HasFlag(enum_LAUNCH_FLAGS.LAUNCH_NODEBUG); // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop LaunchOptions launchOptions = LaunchOptions.GetInstance(_configStore, exe, args, dir, options, noDebug, _engineCallback, TargetEngine.Native, Logger); StartDebugging(launchOptions); EngineUtils.RequireOk(port.GetProcess(_debuggedProcess.Id, out process)); return(Constants.S_OK); } catch (Exception e) when(ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true)) { exception = e; // Return from the catch block so that we can let the exception unwind - the stack can get kind of big } // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and then // return E_ABORT. OnStartDebuggingFailed(exception); return(Constants.E_ABORT); }
int IDebugProgram3.GetProcess(out IDebugProcess2 ppProcess) { return(IDebugProgram2.GetProcess(out ppProcess)); }
int IDebugProgram2.GetProcess(out IDebugProcess2 ppProcess) { ppProcess = null; return(VSConstants.E_NOTIMPL); }
int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 pProcess) { return(IDebugProgram2.Detach()); }
int Microsoft.VisualStudio.Debugger.Interop.IDebugPort2.GetProcess(AD_PROCESS_ID ProcessId, out IDebugProcess2 ppProcess) { ppProcess = ((DebugPort)this).GetProcess(ProcessId); return(COM_HResults.BOOL_TO_HRESULT_FAIL(ppProcess != null)); }
// 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 Constants.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 Constants.E_FAIL; } // NOTE: We wait for the program create event to be continued before we really resume the process return Constants.S_OK; } catch (MIException e) { return e.HResult; } catch (Exception e) when (ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true)) { return EngineUtils.UnexpectedException(e); } }
int Microsoft.VisualStudio.Debugger.Interop.IDebugPortEx2.LaunchSuspended(string pszExe, string pszArgs, string pszDir, string bstrEnv, uint hStdInput, uint hStdOutput, uint hStdError, out IDebugProcess2 ppPortProcess) { ppPortProcess = null; return(COM_HResults.S_OK); }
public int ResumeProcess(IDebugProcess2 process) => throw new NotImplementedException("Launching a local process is not supported. The engine must be launched with DebugLaunchOperation.AlreadyRunning");
int Microsoft.VisualStudio.Debugger.Interop.IDebugPortEx2.CanTerminateProcess(IDebugProcess2 pPortProcess) { return(COM_HResults.S_OK); }
int Microsoft.VisualStudio.Debugger.Interop.IDebugProgram2.GetProcess(out IDebugProcess2 ppProcess) { ppProcess = m_process; return(COM_HResults.S_OK); }
// 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 Constants.S_FALSE; } try { _pollThread.RunOperation(() => _debuggedProcess.CmdTerminate()); _debuggedProcess.Terminate(); } catch (ObjectDisposedException) { // Ignore failures caused by the connection already being dead. } return Constants.S_OK; }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(_pollThread == null); Debug.Assert(_engineCallback == null); Debug.Assert(_debuggedProcess == null); Debug.Assert(_ad7ProgramId == Guid.Empty); process = null; _engineCallback = new EngineCallback(this, ad7Callback); Exception exception; try { // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop LaunchOptions launchOptions = LaunchOptions.GetInstance(_registryRoot, exe, args, dir, options, _engineCallback, TargetEngine.Native); // We are being asked to debug a process when we currently aren't debugging anything _pollThread = new WorkerThread(); var cancellationTokenSource = new CancellationTokenSource(); using (cancellationTokenSource) { _pollThread.RunOperation(ResourceStrings.InitializingDebugger, cancellationTokenSource, (MICore.WaitLoop waitLoop) => { try { _debuggedProcess = new DebuggedProcess(true, launchOptions, _engineCallback, _pollThread, _breakpointManager, this, _registryRoot); } finally { // If there is an exception from the DebuggeedProcess constructor, it is our responsibility to dispose the DeviceAppLauncher, // otherwise the DebuggedProcess object takes ownership. if (_debuggedProcess == null && launchOptions.DeviceAppLauncher != null) { launchOptions.DeviceAppLauncher.Dispose(); } } _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError; return(_debuggedProcess.Initialize(waitLoop, cancellationTokenSource.Token)); }); } EngineUtils.RequireOk(port.GetProcess(_debuggedProcess.Id, out process)); return(Constants.S_OK); } catch (Exception e) { exception = e; // Return from the catch block so that we can let the exception unwind - the stack can get kind of big } // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and then // return E_ABORT. Logger.Flush(); SendStartDebuggingError(exception); Dispose(); return(Constants.E_ABORT); }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { process = null; if (_mixedMode) { return VSConstants.E_NOTIMPL; } Debug.WriteLine("--------------------------------------------------------------------------------"); Debug.WriteLine("PythonEngine LaunchSuspended Begin " + launchFlags + " " + GetHashCode()); AssertMainThread(); Debug.Assert(_events == null); Debug.Assert(_process == null); Debug.Assert(_ad7ProgramId == Guid.Empty); _events = ad7Callback; _engineCreated = _programCreated = false; _loadComplete.Reset(); if (options != null) { ParseOptions(options); } Send(new AD7CustomEvent(VsPackageMessage.SetDebugOptions, this), AD7CustomEvent.IID, null, null); // If this is a windowed application, there's no console to wait on, so disable those flags if they were set. if (_debugOptions.HasFlag(PythonDebugOptions.IsWindowsApplication)) { _debugOptions &= ~(PythonDebugOptions.WaitOnNormalExit | PythonDebugOptions.WaitOnAbnormalExit); } Guid processId; if (_debugOptions.HasFlag(PythonDebugOptions.AttachRunning)) { if (!Guid.TryParse(exe, out processId)) { Debug.Fail("When PythonDebugOptions.AttachRunning is used, the 'exe' parameter must be a debug session GUID."); return VSConstants.E_INVALIDARG; } _process = DebugConnectionListener.GetProcess(processId); _attached = true; _pseudoAttach = true; } else { _process = new PythonProcess(_languageVersion, exe, args, dir, env, _interpreterOptions, _debugOptions, _dirMapping); } if (!_debugOptions.HasFlag(PythonDebugOptions.AttachRunning)) { _process.Start(false); } AttachEvents(_process); AD_PROCESS_ID adProcessId = new AD_PROCESS_ID(); adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = (uint)_process.Id; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); Debug.WriteLine("PythonEngine LaunchSuspended returning S_OK"); Debug.Assert(process != null); Debug.Assert(!_process.HasExited); return VSConstants.S_OK; }
public int GetProcess(out IDebugProcess2 ppProcess) { ppProcess = _process; return(0); }
// 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) { if (_mixedMode) { return VSConstants.E_NOTIMPL; } Debug.WriteLine("PythonEngine TerminateProcess"); AssertMainThread(); Debug.Assert(_events != null); Debug.Assert(_process != null); int processId = EngineUtils.GetProcessId(process); if (processId != _process.Id) { return VSConstants.S_FALSE; } var detaching = EngineDetaching; if (detaching != null) { detaching(this, new AD7EngineEventArgs(this)); } if (!_pseudoAttach) { _process.Terminate(); } else { _process.Detach(); } return VSConstants.S_OK; }
public int GetProcess(out IDebugProcess2 process) { process = this.process; return(VSConstants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int TerminateProcess (IDebugProcess2 process) { // // Terminate a process launched by IDebugEngineLaunch2.LaunchSuspended. // // The debugger will call IDebugEngineLaunch2.CanTerminateProcess before calling this method. // LoggingUtils.PrintFunction (); try { DebuggeeProcess debugProcess = (process as DebuggeeProcess); LoggingUtils.RequireOk (debugProcess.Terminate ()); Detach (debugProcess.DebuggeeProgram); return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); return Constants.E_FAIL; } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int LaunchSuspended (string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { // // Normally, VS launches a program using the IDebugPortEx2::LaunchSuspended method, and the attaches the debugger to the suspended program. // However, there are circumstances in which the DebugEngine may need to launch a program or other dependencies (e.g. tools or interpreters) in which case this method is used. // IDebugEngineLaunch2::ResumeProcess method is called to start the process after the program has been launched in a suspended state. // LoggingUtils.PrintFunction (); try { if (port == null) { throw new ArgumentNullException ("port"); } if (string.IsNullOrEmpty (exe)) { throw new ArgumentNullException ("exe"); } if (!File.Exists (exe)) { throw new FileNotFoundException ("Failed to find target application: " + exe); } m_sdmCallback = new DebugEngineCallback (this, ad7Callback); DebuggeePort debuggeePort = port as DebuggeePort; DebuggeeProcess debugProcess = null; // // Evaluate options; including current debugger target application. // if (m_launchConfiguration == null) { throw new InvalidOperationException ("No launch configuration found."); } m_launchConfiguration.FromString (options); string packageName = m_launchConfiguration ["PackageName"]; string launchActivity = m_launchConfiguration ["LaunchActivity"]; bool debugMode = m_launchConfiguration ["DebugMode"].Equals ("true"); bool openGlTrace = m_launchConfiguration ["OpenGlTrace"].Equals ("true"); bool appIsRunning = false; // // Cache any LaunchSuspended specific parameters. // m_launchConfiguration ["LaunchSuspendedExe"] = exe; m_launchConfiguration ["LaunchSuspendedDir"] = dir; m_launchConfiguration ["LaunchSuspendedEnv"] = env; // // Prevent blocking the main VS thread when launching a suspended application. // Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.ShowDialog, string.Empty), null, null); ManualResetEvent launchSuspendedMutex = new ManualResetEvent (false); Thread asyncLaunchSuspendedThread = new Thread (delegate () { try { // // Launch application on device in a 'suspended' state. // Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Starting '{0}'...", packageName)), null, null); if (!appIsRunning) { StringBuilder launchArgumentsBuilder = new StringBuilder (); launchArgumentsBuilder.Append ("start "); if (debugMode) { launchArgumentsBuilder.Append ("-D "); // debug } else { launchArgumentsBuilder.Append ("-W "); // wait } launchArgumentsBuilder.Append ("-S "); // force stop the target app before starting the activity if (openGlTrace) { launchArgumentsBuilder.Append ("--opengl-trace "); } launchArgumentsBuilder.Append (packageName + "/" + launchActivity); Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("[adb:shell:am] {0}", launchArgumentsBuilder)), null, null); string launchResponse = debuggeePort.PortDevice.Shell ("am", launchArgumentsBuilder.ToString ()); if (string.IsNullOrEmpty (launchResponse) || launchResponse.Contains ("Error:")) { throw new InvalidOperationException ("Launch intent failed:\n" + launchResponse); } } // // Query whether the target application is already running. (Double-check) // int launchAttempt = 1; int maxLaunchAttempts = 20; while (!appIsRunning) { Broadcast(new DebugEngineEvent.DebuggerConnectionEvent(DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format("Waiting for '{0}' to launch (Attempt {1} of {2})...", packageName, launchAttempt, maxLaunchAttempts)), null, null); LoggingUtils.RequireOk (debuggeePort.RefreshProcesses ()); // // Validate that the process is running and was spawned by one of the zygote processes. // uint [] zygotePids = debuggeePort.PortDevice.GetPidsFromName ("zygote"); uint [] zygote64Pids = debuggeePort.PortDevice.GetPidsFromName ("zygote64"); uint [] packagePids = debuggeePort.PortDevice.GetPidsFromName (packageName); for (int i = packagePids.Length - 1; i >= 0; --i) { uint pid = packagePids [i]; AndroidProcess packageProcess = debuggeePort.PortDevice.GetProcessFromPid (pid); bool spawnedByZygote = false; if ((zygotePids.Length > 0) && (packageProcess.ParentPid == zygotePids [0])) { spawnedByZygote = true; } else if ((zygote64Pids.Length > 0) && (packageProcess.ParentPid == zygote64Pids [0])) { spawnedByZygote = true; } if (spawnedByZygote) { debugProcess = debuggeePort.GetProcessForPid (pid); appIsRunning = (debugProcess != null); break; } } if (!appIsRunning) { if (++launchAttempt > maxLaunchAttempts) { throw new TimeoutException (string.Format ("'{0}' failed to launch. Please ensure device is unlocked.", packageName)); } Application.DoEvents (); Thread.Sleep (100); } } launchSuspendedMutex.Set (); } catch (Exception e) { LoggingUtils.HandleException (e); string error = string.Format ("[Exception] {0}\n{1}", e.Message, e.StackTrace); Broadcast (ad7Callback, new DebugEngineEvent.Error (error, true), null, null); launchSuspendedMutex.Set (); } }); asyncLaunchSuspendedThread.Start (); while (!launchSuspendedMutex.WaitOne (0)) { Application.DoEvents (); Thread.Sleep (100); } // // Attach to launched process. // if (debugProcess == null) { throw new InvalidOperationException (string.Format ("'{0}' failed to launch. Could not continue.", packageName)); } process = debugProcess; return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); process = null; try { string error = string.Format ("[Exception] {0}\n{1}", e.Message, e.StackTrace); Broadcast (ad7Callback, new DebugEngineEvent.Error (error, true), null, null); } catch { LoggingUtils.HandleException (e); } return Constants.E_FAIL; } }
public JavaDebugProgram(IDebugProcess2 process) { Contract.Requires<ArgumentNullException>(process != null, "process"); _process = process; }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(_events == null); Debug.Assert(_process == null); Debug.Assert(_ad7ProgramId == Guid.Empty); _events = ad7Callback; List <string[]> dirMapping = null; Guid processId; if (Guid.TryParse(exe, out processId)) { _process = DebugConnectionListener.GetProcess(processId); _attached = true; _pseudoAttach = true; } else { _process = new NodeProcess(exe, args, dir, BreakOnAllExceptions, dirMapping); } _programCreated = false; AttachProcessEvents(_process); _process.Start(); var adProcessId = new AD_PROCESS_ID { ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM, dwProcessId = (uint)_process.Id }; EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); Debug.WriteLine("NodeEngine LaunchSuspended returning S_OK"); Debug.Assert(process != null); Debug.Assert(!_process.HasExited); return(VSConstants.S_OK); }
int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 pProcess) { return(VSConstants.E_NOTIMPL); }
// Determines if a process can be terminated. int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 process) { if (_mixedMode) { return VSConstants.S_OK; } Debug.WriteLine("PythonEngine CanTerminateProcess"); AssertMainThread(); Debug.Assert(_events != null); Debug.Assert(_process != null); int processId = EngineUtils.GetProcessId(process); if (processId == _process.Id) { return VSConstants.S_OK; } else { return VSConstants.S_FALSE; } }
int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 pProcess) { Debug.WriteLine("AD7Engine CanTerminateProcess"); return(VSConstants.S_OK); }
// Resume a process launched by IDebugEngineLaunch2.LaunchSuspended int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process) { if (_mixedMode) { return VSConstants.E_NOTIMPL; } Debug.WriteLine("Python Debugger ResumeProcess Begin"); AssertMainThread(); if (_events == null) { // process failed to start Debug.WriteLine("ResumeProcess fails, no events"); return VSConstants.E_FAIL; } 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)); IDebugDefaultPort2 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; }
int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { Debug.WriteLine("AD7Engine LaunchSuspended"); ppProcess = new AD7Process(pPort); _node = (ppProcess as AD7Process).Node; _node.FileName = pszExe; _node.ConnectionString = pszArgs; _events = new AD7Events(this, pCallback); // Gets active window handler to use in modals IntPtr handler = GetForegroundWindow(); _node.ParentWindow = new System.Windows.Forms.NativeWindow(); _node.ParentWindow.AssignHandle(handler); return(VSConstants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int ResumeProcess (IDebugProcess2 process) { // // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended // LoggingUtils.PrintFunction (); try { // // 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; DebuggeeProcess debugProcess = process as DebuggeeProcess; LoggingUtils.RequireOk (debugProcess.GetPort (out port)); DebuggeePort debugPort = port as DebuggeePort; LoggingUtils.RequireOk (debugPort.AddProgramNode (debugProcess.DebuggeeProgram)); return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); return Constants.E_FAIL; } }
public int GetProcess(out IDebugProcess2 ppProcess) { ppProcess = _process; return(VSConstants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endregion //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugEngineLaunch2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int CanTerminateProcess (IDebugProcess2 process) { // // Determines if a process can be terminated. // LoggingUtils.PrintFunction (); return Constants.S_OK; }
public JavaDebugProgram(IDebugProcess2 process) { Contract.Requires <ArgumentNullException>(process != null, "process"); _process = process; }
public int GetProcess(out IDebugProcess2 ppProcess) { ppProcess = _process; return VSConstants.S_OK; }
public static AD_PROCESS_ID GetProcessId(IDebugProcess2 process) { AD_PROCESS_ID[] pid = new AD_PROCESS_ID[1]; EngineUtils.RequireOk(process.GetPhysicalProcessId(pid)); return(pid[0]); }
public int GetProcess(out IDebugProcess2 process) { Debug.Fail("This function is not called by the debugger"); process = null; return Constants.E_NOTIMPL; }
int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 process) => VSConstants.S_OK;
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { Debug.Assert(_pollThread == null); Debug.Assert(_engineCallback == null); Debug.Assert(_debuggedProcess == null); Debug.Assert(_ad7ProgramId == Guid.Empty); // Check if the logger was enabled late. Logger.LoadMIDebugLogger(_configStore); process = null; _engineCallback = new EngineCallback(this, ad7Callback); Exception exception; try { // Note: LaunchOptions.GetInstance can be an expensive operation and may push a wait message loop LaunchOptions launchOptions = LaunchOptions.GetInstance(_configStore, exe, args, dir, options, _engineCallback, TargetEngine.Native, Logger); // We are being asked to debug a process when we currently aren't debugging anything _pollThread = new WorkerThread(Logger); var cancellationTokenSource = new CancellationTokenSource(); using (cancellationTokenSource) { _pollThread.RunOperation(ResourceStrings.InitializingDebugger, cancellationTokenSource, (HostWaitLoop waitLoop) => { try { _debuggedProcess = new DebuggedProcess(true, launchOptions, _engineCallback, _pollThread, _breakpointManager, this, _configStore); } finally { // If there is an exception from the DebuggeedProcess constructor, it is our responsibility to dispose the DeviceAppLauncher, // otherwise the DebuggedProcess object takes ownership. if (_debuggedProcess == null && launchOptions.DeviceAppLauncher != null) { launchOptions.DeviceAppLauncher.Dispose(); } } _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError; return _debuggedProcess.Initialize(waitLoop, cancellationTokenSource.Token); }); } EngineUtils.RequireOk(port.GetProcess(_debuggedProcess.Id, out process)); return Constants.S_OK; } catch (Exception e) when (ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true)) { exception = e; // Return from the catch block so that we can let the exception unwind - the stack can get kind of big } // If we just return the exception as an HRESULT, we will loose our message, so we instead send up an error event, and then // return E_ABORT. Logger.Flush(); SendStartDebuggingError(exception); Dispose(); return Constants.E_ABORT; }
int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 process) => process.Terminate();
// 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 Constants.S_FALSE; } try { _pollThread.RunOperation(() => _debuggedProcess.CmdTerminate()); if (_debuggedProcess.MICommandFactory.Mode != MIMode.Clrdbg) { _debuggedProcess.Terminate(); } else { // Clrdbg issues a proper exit event on CmdTerminate call, don't call _debuggedProcess.Terminate() which // simply sends a fake exit event that overrides the exit code of the real one } } catch (ObjectDisposedException) { // Ignore failures caused by the connection already being dead. } return Constants.S_OK; }
public int LaunchSuspended(string pszServer, IDebugPort2 port, string serverExe, string serverArgs, string dir, string env, string opts, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) => throw new NotImplementedException("Launching a local process is not supported. The engine must be launched with DebugLaunchOperation.AlreadyRunning");