public void FromCommandLineArgsRaceCondition() { // https://pytools.codeplex.com/workitem/1429 var mre = new ManualResetEvent(false); var tasks = new Task <bool> [100]; try { for (int i = 0; i < tasks.Length; i += 1) { tasks[i] = Task.Run(() => { mre.WaitOne(); using (var arg = VisualStudioApp.FromProcessId(123)) { return(arg is VisualStudioApp); } }); } mre.Set(); Assert.IsTrue(Task.WaitAll(tasks, TimeSpan.FromSeconds(30.0))); Assert.IsTrue(tasks.All(t => t.Result)); } finally { mre.Dispose(); Task.WaitAll(tasks, TimeSpan.FromSeconds(30.0)); } }
private static void AttachIfDebugging(Process targetVs) { if (!Debugger.IsAttached) { return; } // We are debugging tests, so attach the debugger to VS var selfId = Process.GetCurrentProcess().Id; foreach (var p in Process.GetProcessesByName("devenv")) { if (p.Id == targetVs.Id) { continue; } using (VisualStudioApp vs = VisualStudioApp.FromProcessId(p.Id)) { EnvDTE.DTE dte; try { dte = vs.GetDTE(); } catch (InvalidOperationException) { // DTE is not available, which means VS has not been running continue; } if (dte.Debugger.CurrentMode == EnvDTE.dbgDebugMode.dbgDesignMode) { // Not the correct VS continue; } foreach (EnvDTE.Process dp in dte.Debugger.DebuggedProcesses) { if (dp.ProcessID == selfId) { // This is the correct VS, so attach and return. vs.AttachToProcess(targetVs, null); return; } } } } }
public void StartOrRestart( string devenvExe, string devenvArguments, string testDataRoot, string tempRoot ) { lock (_lock) { var settings = $"{devenvExe ?? ""};{devenvArguments ?? ""};{testDataRoot ?? ""};{tempRoot ?? ""}"; if (_vs != null && _app != null) { if (_currentSettings == settings) { return; } Console.WriteLine("Restarting VS because settings have changed"); } _currentSettings = settings; CloseCurrentInstance(); var psi = new ProcessStartInfo { FileName = devenvExe, Arguments = devenvArguments, ErrorDialog = false, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; psi.Environment["_PTVS_UI_TEST"] = "1"; if (!string.IsNullOrEmpty(testDataRoot)) { psi.Environment["_TESTDATA_ROOT_PATH"] = testDataRoot; } if (!string.IsNullOrEmpty(tempRoot)) { psi.Environment["_TESTDATA_TEMP_PATH"] = tempRoot; } _vs = Process.Start(psi); if (!NativeMethods.AssignProcessToJobObject(_jobObject, _vs.Handle)) { try { _vs.Kill(); } catch (Exception) { } _vs.Dispose(); throw new InvalidOperationException("Failed to add VS to our job object"); } // Forward console output to our own output, which will // be captured by the test runner. _vs.OutputDataReceived += (s, e) => { if (e.Data != null) { Console.WriteLine(e.Data); } }; _vs.ErrorDataReceived += (s, e) => { if (e.Data != null) { Console.Error.WriteLine(e.Data); } }; _vs.BeginOutputReadLine(); _vs.BeginErrorReadLine(); // Always allow at least five seconds to start Thread.Sleep(5000); if (_vs.HasExited) { throw new InvalidOperationException("Failed to start VS"); } _app = VisualStudioApp.FromProcessId(_vs.Id); var stopAt = DateTime.Now.AddSeconds(60); EnvDTE.DTE dte = null; while (DateTime.Now < stopAt && dte == null) { try { dte = _app.GetDTE(); } catch (InvalidOperationException) { Thread.Sleep(1000); } } if (dte == null) { throw new InvalidOperationException("Failed to start VS"); } AttachIfDebugging(_vs); } }