Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Xunit.Harness
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Serialization.Formatters;
using System.Threading.Tasks;
using Microsoft.VisualStudio.IntegrationTestService;
using Windows.Win32;
using Windows.Win32.Foundation;
Expand All @@ -27,9 +28,10 @@ internal class VisualStudioInstance
private readonly IpcChannel _integrationServiceChannel;
private readonly VisualStudio_InProc _inProc;

public VisualStudioInstance(Process hostProcess, DTE dte, Version version, ImmutableHashSet<string> supportedPackageIds, string installationPath)
public VisualStudioInstance(Process hostProcess, Func<Task> stopWatchingProcessAsync, DTE dte, Version version, ImmutableHashSet<string> supportedPackageIds, string installationPath)
{
HostProcess = hostProcess;
StopWatchingProcessAsync = stopWatchingProcessAsync;
Dte = dte;
Version = version;
SupportedPackageIds = supportedPackageIds;
Expand Down Expand Up @@ -87,6 +89,11 @@ internal Process HostProcess
get;
}

public Func<Task> StopWatchingProcessAsync
{
get;
}

public Version Version
{
get;
Expand Down Expand Up @@ -217,6 +224,8 @@ public void Close(bool exitHostProcess = true)
return;
}

StopWatchingProcessAsync().Wait();

CleanUp();

CloseRemotingService();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,17 @@ private async Task UpdateCurrentlyRunningInstanceAsync(Version version, string?
_currentlyRunningInstance.Close(exitHostProcess: false);
}

_currentlyRunningInstance = new VisualStudioInstance(hostProcess, dte, actualVersion, supportedPackageIds, installationPath);
// Run the snapshot collection operation, but don't block on its completion for the actual test execution
var screenshotTaskCancellationSource = new CancellationTokenSource();
var screenshotTask = Task.Run(() => TakeSnapshotEveryTimeSpanUntilProcessExitAsync(hostProcess, $"devenv{hostProcess.Id}", screenshotTaskCancellationSource.Token));
Func<Task> stopWatchingProcessAsync =
async () =>
{
screenshotTaskCancellationSource.Cancel();
await screenshotTask.ConfigureAwait(false);
};

_currentlyRunningInstance = new VisualStudioInstance(hostProcess, stopWatchingProcessAsync, dte, actualVersion, supportedPackageIds, installationPath);
if (shouldStartNewInstance)
{
var harnessAssemblyDirectory = Path.GetDirectoryName(typeof(VisualStudioInstanceFactory).Assembly.CodeBase);
Expand Down Expand Up @@ -393,25 +403,21 @@ private static async Task<Process> StartNewVisualStudioProcessAsync(string insta
if (version.Major >= 12)
{
var clearCacheProcess = Process.Start(CreateStartInfo(vsExeFile, silent: true, $"/clearcache {vsLaunchArgs}"));
TakeSnapshotEveryTimeSpanUntilProcessExit(clearCacheProcess, "clearcache");
await TakeSnapshotEveryTimeSpanUntilProcessExitAsync(clearCacheProcess, "clearcache", CancellationToken.None);
}

var updateConfigProcess = Process.Start(CreateStartInfo(vsExeFile, silent: true, $"/updateconfiguration {vsLaunchArgs}"));
TakeSnapshotEveryTimeSpanUntilProcessExit(updateConfigProcess, "updateconfiguration");
await TakeSnapshotEveryTimeSpanUntilProcessExitAsync(updateConfigProcess, "updateconfiguration", CancellationToken.None);

var resetSettingsProcess = Process.Start(CreateStartInfo(vsExeFile, silent: true, $"/resetsettings General.vssettings /command \"File.Exit\" {vsLaunchArgs}"));
TakeSnapshotEveryTimeSpanUntilProcessExit(resetSettingsProcess, "resetsettings");
await TakeSnapshotEveryTimeSpanUntilProcessExitAsync(resetSettingsProcess, "resetsettings", CancellationToken.None);

// Make sure we kill any leftover processes spawned by the host
IntegrationHelper.KillProcess("DbgCLR");
IntegrationHelper.KillProcess("VsJITDebugger");
IntegrationHelper.KillProcess("dexplore");

var process = Process.Start(CreateStartInfo(vsExeFile, silent: false, vsLaunchArgs));

// Run the snapshot collection operation, but don't block on its completion for the actual test execution
_ = Task.Run(() => TakeSnapshotEveryTimeSpanUntilProcessExit(process, $"devenv{process.Id}"));

Debug.WriteLine($"Launched a new instance of Visual Studio. (ID: {process.Id})");

return process;
Expand Down Expand Up @@ -464,26 +470,30 @@ private static string ExtractIntegrationTestServiceExtension(string temporaryFol
return path;
}

private static void TakeSnapshotEveryTimeSpanUntilProcessExit(Process process, string commandBeingExecuted)
private static async Task TakeSnapshotEveryTimeSpanUntilProcessExitAsync(Process process, string commandBeingExecuted, CancellationToken cancellationToken)
{
var dir = DataCollectionService.GetLogDirectory();
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}

using var cancellatokenSource = new CancellationTokenSource();
using var cancellationTokenSource = new CancellationTokenSource();
using var linkedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, cancellationToken);

var screenshotTask = Task.Run(() => TakeScreenShotEveryTimeIntervalAsync(dir, commandBeingExecuted, linkedCancellationSource.Token), linkedCancellationSource.Token);

try
{
_ = Task.Run(() => TakeScreenShotEveryTimeIntervalAsync(dir, commandBeingExecuted, cancellatokenSource.Token));
process.WaitForExit();
}
finally
{
cancellatokenSource.Cancel();
cancellationTokenSource.Cancel();
}

await screenshotTask.ConfigureAwait(false);

static async Task TakeScreenShotEveryTimeIntervalAsync(string directory, string commandBeingExecuted, CancellationToken cancellationToken)
{
var count = 1;
Expand Down