Skip to content

Commit

Permalink
Enable nullable on AttachVS (#3671)
Browse files Browse the repository at this point in the history
  • Loading branch information
Evangelink authored May 26, 2022
1 parent f5b768a commit 7d87684
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 43 deletions.
92 changes: 52 additions & 40 deletions src/AttachVS/AttachVs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
using System.Runtime.InteropServices.ComTypes;
using System.Threading;

#nullable disable

namespace Microsoft.TestPlatform.AttachVS;

internal class DebuggerUtility
Expand All @@ -25,20 +23,23 @@ internal static bool AttachVSToProcess(int? pid, int? vsPid)
Trace($"FAIL: Pid is null.");
return false;
}

var process = Process.GetProcessById(pid.Value);
Trace($"Starting with pid '{pid}({process?.ProcessName})', and vsPid '{vsPid}'");
Trace($"Starting with pid '{pid}({process.ProcessName})', and vsPid '{vsPid}'");
Trace($"Using pid: {pid} to get parent VS.");
var vs = GetVsFromPid(Process.GetProcessById(vsPid ?? process.Id));

if (vs != null)
{
Trace($"Parent VS is {vs.ProcessName} ({vs.Id}).");
AttachTo(process, vs);
return true;
}
else
{
Trace($"Parent VS not found, finding the first VS that started.");
var processes = Process.GetProcesses().Where(p => p.ProcessName == "devenv").Select(p =>

Trace($"Parent VS not found, finding the first VS that started.");
var firstVs = Process.GetProcesses()
.Where(p => p.ProcessName == "devenv")
.Select(p =>
{
try
{
Expand All @@ -48,19 +49,26 @@ internal static bool AttachVSToProcess(int? pid, int? vsPid)
{
return null;
}
}).Where(p => p != null && !p.HasExited).OrderBy(p => p.StartTime).ToList();
})
.Where(p => p != null && !p.HasExited)
.OrderBy(p => p!.StartTime)
.FirstOrDefault();

var firstVs = processes.FirstOrDefault();
if (firstVs != null)
{
Trace($"Found VS {firstVs.Process.Id}");
AttachTo(process, firstVs.Process);
return true;
}
return true;

Trace("Could not find any started VS.");
}
catch (Exception ex)
{
Trace($"ERROR: {ex}, {ex.StackTrace}");
return false;
}

return false;
}

private static void AttachTo(Process process, Process vs)
Expand All @@ -79,9 +87,9 @@ private static void AttachTo(Process process, Process vs)

private static bool AttachVs(Process vs, int pid)
{
IBindCtx bindCtx = null;
IRunningObjectTable runninObjectTable = null;
IEnumMoniker enumMoniker = null;
IBindCtx? bindCtx = null;
IRunningObjectTable? runninObjectTable = null;
IEnumMoniker? enumMoniker = null;
try
{
var r = CreateBindCtx(0, out bindCtx);
Expand Down Expand Up @@ -183,18 +191,18 @@ private static bool AttachVs(Process vs, int pid)
}
}

private static Process GetVsFromPid(Process process)
private static Process? GetVsFromPid(Process process)
{
var parent = process;
while (!IsVsOrNull(parent))
{
parent = GetParentProcess(parent);
parent = GetParentProcess(parent!);
}

return parent;
}

private static bool IsVsOrNull(Process process)
private static bool IsVsOrNull(Process? process)
{
if (process == null)
{
Expand All @@ -219,57 +227,61 @@ private static bool IsCorrectParent(Process currentProcess, Process parent)
{
try
{
// Parent needs to start before the child, otherwise it might be a different process
// Parent needs to start before the child, otherwise it might be a different process
// that is just reusing the same PID.
if (parent.StartTime <= currentProcess.StartTime)
{
return true;
}

Trace($"Process {parent.ProcessName} ({parent.Id}) is not a valid parent because it started after the current process.");
return false;
}
catch
{
// Access denied or process exited while we were holding the Process object.
return false;
}

return false;
}

private static Process GetParentProcess(Process process)
private static Process? GetParentProcess(Process process)
{
int id;
try
{
var handle = process.Handle;
var res = NtQueryInformationProcess(handle, 0, out var pbi, Marshal.SizeOf<PROCESS_BASIC_INFORMATION>(), out int size);

var p = res != 0 ? -1 : pbi.InheritedFromUniqueProcessId.ToInt32();

id = p;
}
catch
{
id = -1;
}

Process parent = null;
int id = GetParentProcessId(process);
if (id != -1)
{
try
{
parent = Process.GetProcessById(id);
var parent = Process.GetProcessById(id);
if (IsCorrectParent(process, parent))
return parent;
}
catch
{
// throws when parent no longer runs
}
}

return IsCorrectParent(process, parent) ? parent : null;
return null;

static int GetParentProcessId(Process process)
{
try
{
var handle = process.Handle;
var res = NtQueryInformationProcess(handle, 0, out var pbi, Marshal.SizeOf<PROCESS_BASIC_INFORMATION>(), out int size);

var p = res != 0 ? -1 : pbi.InheritedFromUniqueProcessId.ToInt32();

return p;
}
catch
{
return -1;
}
}
}

private static void Trace(string message, [CallerMemberName] string methodName = null)
private static void Trace(string message, [CallerMemberName] string? methodName = null)
{
System.Diagnostics.Trace.WriteLine($"[AttachVS]{methodName}: {message}");
}
Expand Down
4 changes: 1 addition & 3 deletions src/AttachVS/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
using System.Diagnostics;
using System.Linq;

#nullable disable

namespace Microsoft.TestPlatform.AttachVS;

internal class Program
{
static void Main(string[] args)
static void Main(string[] args!!)
{
Trace.Listeners.Add(new ConsoleTraceListener());

Expand Down

0 comments on commit 7d87684

Please sign in to comment.