Один проект, над которым я работаю, запускает локальные процессы во время тестирования. Среди прочего он запускает экземпляр IISExpress, работающий на веб-сайте .NET.
Я могу отладить код веб-сайта, вручную подключив отладчик к процессу IISExpress. Тем не менее, я хотел бы автоматизировать этот ручной шаг.
Ниже приведен код, который у меня есть. Кажется, он находит процесс, к которому нужно присоединиться (то есть Attach2
называется). Однако точки останова в коде веб-сайта по-прежнему не достигаются даже после вызова Attach2
(они отображаются в виде красного круга с белой заливкой).
Что я делаю не так?
public class DebuggerHelper
{
[DllImport("ole32.dll")]
private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
public static bool TryAttachProcessesToVisualStudioDebuggingCurrentProcess(params int[] processIds)
{
var notAttached = processIds.Length;
var currentProcessId = System.Diagnostics.Process.GetCurrentProcess().Id;
IBindCtx bindCtx = null;
IRunningObjectTable runningObjectTable = null;
IEnumMoniker enumMonikers = null;
try
{
Marshal.ThrowExceptionForHR(CreateBindCtx(0, out bindCtx));
bindCtx.GetRunningObjectTable(out runningObjectTable);
runningObjectTable.EnumRunning(out enumMonikers);
enumMonikers.Reset();
var numFetched = IntPtr.Zero;
var monikers = new IMoniker[1];
while (enumMonikers.Next(1, monikers, numFetched) == 0)
{
monikers[0].GetDisplayName(bindCtx, null, out var runningObjectName);
runningObjectTable.GetObject(monikers[0], out var runningObjectVal);
if (runningObjectVal is EnvDTE80.DTE2 dte
&& runningObjectName.StartsWith("!VisualStudio.DTE.15.0"))
{
foreach (EnvDTE80.Process2 debuggedProcess in dte.Debugger.DebuggedProcesses)
{
if (debuggedProcess.ProcessID == currentProcessId)
{
foreach (EnvDTE80.Process2 localProcess in dte.Debugger.LocalProcesses)
{
if (processIds.Contains(localProcess.ProcessID))
{
localProcess.Attach();
notAttached--;
}
}
}
}
}
}
return notAttached == 0;
}
finally
{
if (enumMonikers != null)
{
Marshal.ReleaseComObject(enumMonikers);
}
if (runningObjectTable != null)
{
Marshal.ReleaseComObject(runningObjectTable);
}
if (bindCtx != null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
}
}
Редактировать: Похоже, что он несколько привязан, но что-то не так. Я получаю следующее: