// 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 lose our message, so we instead send up an error event, and then // return E_ABORT. OnStartDebuggingFailed(exception); 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) { 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); // 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); } 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); }
private LaunchOptions GetLaunchOptions(string content) { return(LaunchOptions.GetInstance(null, "bogus-exe-path", null, null, content, null, TargetEngine.Native, null)); }
private LaunchOptions GetLaunchOptions(string content) { return(LaunchOptions.GetInstance("bogus-registry-root", "bogus-exe-path", null, null, content, null)); }