private static async Task StartNewVisualStudioProcessAsync()

in src/Microsoft.VisualStudio.Extensibility.Testing.Xunit.Shared/Harness/VisualStudioInstanceFactory.cs [326:412]


        private static async Task<Process> StartNewVisualStudioProcessAsync(string installationPath, Version version, string? rootSuffix, ImmutableList<string> extensionFiles)
        {
            var vsExeFile = Path.Combine(installationPath, @"Common7\IDE\devenv.exe");
            var vsRegEditExeFile = Path.Combine(installationPath, @"Common7\IDE\VsRegEdit.exe");

            var temporaryFolder = Path.Combine(Path.GetTempPath(), "vs-extension-testing", Path.GetRandomFileName());
            Assert.False(Directory.Exists(temporaryFolder));
            Directory.CreateDirectory(temporaryFolder);

            var installerAssemblyPath = ExtractInstallerAssembly(version, temporaryFolder);

            var integrationTestServiceExtension = ExtractIntegrationTestServiceExtension(temporaryFolder);
            var extensions = extensionFiles.Add(integrationTestServiceExtension);

            try
            {
                var arguments = string.Join(
                    " ",
                    $"\"{rootSuffix}\"",
                    $"\"{installationPath}\"",
                    string.Join(" ", extensions.Select(extension => $"\"{extension}\"")));

                var installProcessStartInfo = CreateSilentStartInfo(installerAssemblyPath, arguments);
                installProcessStartInfo.RedirectStandardError = true;
                installProcessStartInfo.RedirectStandardOutput = true;
                using var installProcess = Process.Start(installProcessStartInfo);
                var standardErrorAsync = installProcess.StandardError.ReadToEndAsync();
                var standardOutputAsync = installProcess.StandardOutput.ReadToEndAsync();
                installProcess.WaitForExit();

                if (installProcess.ExitCode != 0)
                {
                    var messageBuilder = new StringBuilder();
                    messageBuilder.AppendLine($"VSIX installer failed with exit code: {installProcess.ExitCode}");
                    messageBuilder.AppendLine();
                    messageBuilder.AppendLine($"Standard Error:");
                    messageBuilder.AppendLine(await standardErrorAsync.ConfigureAwait(true));
                    messageBuilder.AppendLine();
                    messageBuilder.AppendLine($"Standard Output:");
                    messageBuilder.AppendLine(await standardOutputAsync.ConfigureAwait(true));

                    throw new InvalidOperationException(messageBuilder.ToString());
                }
            }
            finally
            {
                File.Delete(integrationTestServiceExtension);
                Directory.Delete(temporaryFolder, recursive: true);
            }

            if (version.Major >= 16)
            {
                // Make sure the start window doesn't show on launch
                Process.Start(CreateSilentStartInfo(vsRegEditExeFile, $"set \"{installationPath}\" \"{rootSuffix}\" HKCU General OnEnvironmentStartup dword 10")).WaitForExit();
            }

            var vsLaunchArgs = string.Empty;
            if (!string.IsNullOrWhiteSpace(rootSuffix))
            {
                vsLaunchArgs += $"/rootsuffix \"{rootSuffix}\"";
            }

            // BUG: Currently building with /p:DeployExtension=true does not always cause the MEF cache to recompose...
            //      So, run clearcache and updateconfiguration to workaround https://devdiv.visualstudio.com/DevDiv/_workitems?id=385351.
            if (version.Major >= 12)
            {
                Process.Start(CreateSilentStartInfo(vsExeFile, $"/clearcache {vsLaunchArgs}")).WaitForExit();
            }

            Process.Start(CreateSilentStartInfo(vsExeFile, $"/updateconfiguration {vsLaunchArgs}")).WaitForExit();
            Process.Start(CreateSilentStartInfo(vsExeFile, $"/resetsettings General.vssettings /command \"File.Exit\" {vsLaunchArgs}")).WaitForExit();

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

            var process = Process.Start(vsExeFile, vsLaunchArgs);
            Debug.WriteLine($"Launched a new instance of Visual Studio. (ID: {process.Id})");

            return process;

            ProcessStartInfo CreateSilentStartInfo(string fileName, string arguments)
            {
                return new ProcessStartInfo(fileName, arguments) { CreateNoWindow = true, UseShellExecute = false };
            }
        }