public static void AttachToProcess(Process[] processes, ChildDebuggingMode mode) { List<VsDebugTargetInfo2> targetList = new List<VsDebugTargetInfo2>(); IntPtr targetsBuffer = IntPtr.Zero; int targetSize = Marshal.SizeOf(typeof(VsDebugTargetInfo2)); int guidSize = Marshal.SizeOf(typeof(Guid)); try { foreach (Process process in processes) { NtProcess ntproc = new NtProcess(process.Id); VsDebugTargetInfo2 target = new VsDebugTargetInfo2(); DebugProcessOptions options = new DebugProcessOptions { ChildDebuggingMode = mode }; target.dwDebugEngineCount = 1; target.dwProcessId = (uint)process.Id; target.dlo = (uint)DEBUG_LAUNCH_OPERATION.DLO_AlreadyRunning; if (process.Threads.Count == 1) { // If this is a suspended process, then using DLO_AttachToSuspendedLaunchProcess will // bypass the initial loader breakpoint, causing a seamless and transparent attach. // This is usually the desired behavior, as child processes frequently startup and // shutdown, and it is intrusive to be constantly breaking into the debugger. ProcessThread mainThread = process.Threads[0]; if (mainThread.ThreadState == ThreadState.Wait && mainThread.WaitReason == ThreadWaitReason.Suspended) target.dlo |= (uint)_DEBUG_LAUNCH_OPERATION4.DLO_AttachToSuspendedLaunchProcess; } target.bstrExe = ntproc.Win32ProcessImagePath; target.cbSize = (uint)targetSize; target.bstrCurDir = null; target.guidPortSupplier = DkmIntegration.Guids.PortSupplier.Default; target.LaunchFlags = (uint)(__VSDBGLAUNCHFLAGS.DBGLAUNCH_Silent | __VSDBGLAUNCHFLAGS.DBGLAUNCH_WaitForAttachComplete); target.bstrOptions = options.OptionsString; target.pDebugEngines = Marshal.AllocCoTaskMem(guidSize); Marshal.StructureToPtr(DkmEngineId.NativeEng, target.pDebugEngines, false); targetList.Add(target); } int elementSize = Marshal.SizeOf(typeof(VsDebugTargetInfo2)); targetsBuffer = Marshal.AllocCoTaskMem(targetList.Count * elementSize); for (int i = 0; i < targetList.Count; ++i) { IntPtr writeAddr = targetsBuffer + i * elementSize; Marshal.StructureToPtr(targetList[i], writeAddr, false); } IVsDebugger2 debugger = (IVsDebugger2)VsPackage.GetGlobalService(typeof(SVsShellDebugger)); Core.Logger.Log("Launching {0} debug targets", processes.Length); int hr = debugger.LaunchDebugTargets2((uint)processes.Length, targetsBuffer); if (hr != 0) { IVsUIShell shell = (IVsUIShell)VsPackage.GetGlobalService(typeof(SVsUIShell)); string error; shell.GetErrorInfo(out error); Core.Logger.LogError("An error occured while attaching to process (hr = 0x{0:x}). {1}", hr, error); } } finally { foreach (VsDebugTargetInfo2 target in targetList) { if (target.pDebugEngines != IntPtr.Zero) Marshal.FreeCoTaskMem(target.pDebugEngines); } if (targetsBuffer != IntPtr.Zero) Marshal.FreeCoTaskMem(targetsBuffer); } }
public DebugProcessOptions CopyTo(DebugProcessOptions other) { other.DebuggeeVersion = this.DebuggeeVersion; other.Filename = this.Filename; other.CommandLine = this.CommandLine; other.CurrentDirectory = this.CurrentDirectory; other.InheritHandles = this.InheritHandles; other.ProcessCreationFlags = this.ProcessCreationFlags; other.DebugMessageDispatcher = this.DebugMessageDispatcher; other.DebugOptions = this.DebugOptions == null ? null : this.DebugOptions.Clone(); other.BreakProcessType = this.BreakProcessType; return other; }
private static bool ShouldEnableChildDebugging(DkmProcess process, DebugProcessOptions options) { if (options.ChildDebuggingMode == ChildDebuggingMode.AlwaysAttach) return true; if (options.ChildDebuggingMode == ChildDebuggingMode.UseDefault) { Logger.LogInfo( "Requesting default child process debugging mode for process {0}.", process.UniqueId); DkmCustomMessage attachRequest = DkmCustomMessage.Create( process.Connection, process, PackageServices.VsPackageMessageGuid, (int)VsPackageMessage.IsChildDebuggingEnabled, process.UniqueId, process.Connection.UniqueId); // This needs to happen synchronously in order to guarantee that child debugging is enabled // before the process finishes initializing. attachRequest.SendToVsService(PackageServices.DkmComponentEventHandler, true); } return false; }
public DebugProcessOptions CopyTo(DebugProcessOptions other) { other.DebuggeeVersion = this.DebuggeeVersion; other.DebugMessageDispatcher = this.DebugMessageDispatcher; other.DebugOptions = this.DebugOptions == null ? null : this.DebugOptions.Clone(); return other; }
public ProcessDebugOptionsDataItem(DebugProcessOptions options) { this._options = options; }
public DebugProcessOptions CopyTo(DebugProcessOptions other) { other.CLRTypeDebugInfo = CLRTypeDebugInfo.Clone(); other.Filename = Filename; other.CommandLine = CommandLine; other.CurrentDirectory = CurrentDirectory; other.InheritHandles = InheritHandles; other.ProcessCreationFlags = ProcessCreationFlags; other.DebugMessageDispatcher = DebugMessageDispatcher; other.DebugOptions = DebugOptions == null ? null : DebugOptions.Clone(); other.BreakProcessKind = BreakProcessKind; return other; }