public void DragDropFileToContainingFolderTest(PythonVisualStudioApp app) { var project = app.OpenProject(@"TestData\DragDropTest.sln"); var window = app.OpenSolutionExplorer(); Mouse.MoveTo(window.FindChildOfProject(project, "TestFolder", "SubItem2.py").Element.GetClickablePoint()); Mouse.Down(MouseButton.Left); Mouse.MoveTo(window.FindChildOfProject(project, "TestFolder").Element.GetClickablePoint()); Mouse.Up(MouseButton.Left); using (var dlg = AutomationDialog.WaitForDialog(app)) { } window.WaitForChildOfProject(project, "TestFolder", "SubItem2.py"); }
public void WebProjectCreateVirtualEnvOnNew() { using (var app = new VisualStudioApp()) { var t = Task.Run(() => app.CreateProject( PythonVisualStudioApp.TemplateLanguageName, PythonVisualStudioApp.FlaskWebProjectTemplate, TestData.GetTempPath(), "WebProjectCreateVirtualEnvOnNew", suppressUI: false )); using (var dlg = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(t)))) { // Create a virtual environment dlg.ClickButtonAndClose("CommandLink_1000", nameIsAutomationId: true); } using (var dlg = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(t)))) { dlg.ClickButtonByAutomationId("Create"); dlg.ClickButtonAndClose("Close", nameIsAutomationId: true); } var project = TaskExt.WaitAndUnwrapExceptions(t); var provider = project.Properties.Item("InterpreterFactoryProvider").Value as MSBuildProjectInterpreterFactoryProvider; for (int retries = 20; retries > 0; --retries) { if (provider.IsProjectSpecific(provider.ActiveInterpreter)) { break; } Thread.Sleep(1000); } Assert.IsTrue(provider.IsProjectSpecific(provider.ActiveInterpreter), "Did not have virtualenv"); for (int retries = 60; retries > 0; --retries) { if (InterpreterExt.FindModules(provider.ActiveInterpreter, "flask").Any()) { break; } Thread.Sleep(1000); } AssertUtil.ContainsExactly( InterpreterExt.FindModules(provider.ActiveInterpreter, "flask"), "flask" ); } }
public void WebProjectCreateVirtualEnvOnNew() { using (var app = new PythonVisualStudioApp()) { var t = Task.Run(() => app.CreateProject( PythonVisualStudioApp.TemplateLanguageName, PythonVisualStudioApp.FlaskWebProjectTemplate, TestData.GetTempPath(), "WebProjectCreateVirtualEnvOnNew", suppressUI: false )); using (var dlg = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(t)))) { // Create a virtual environment dlg.ClickButtonAndClose("CommandLink_1000", nameIsAutomationId: true); } using (var dlg = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(t)))) { dlg.ClickButtonByAutomationId("Create"); dlg.ClickButtonAndClose("Close", nameIsAutomationId: true); } var project = t.WaitAndUnwrapExceptions(); var contextProvider = app.ComponentModel.GetService <VsProjectContextProvider>(); for (int retries = 20; retries > 0; --retries) { if (contextProvider.IsProjectSpecific(project.GetPythonProject().ActiveInterpreter.Configuration)) { break; } Thread.Sleep(1000); } Assert.IsTrue(contextProvider.IsProjectSpecific(project.GetPythonProject().ActiveInterpreter.Configuration), "Did not have virtualenv"); for (int retries = 60; retries > 0; --retries) { if (project.GetPythonProject().ActiveInterpreter.FindModules("flask").Any()) { break; } Thread.Sleep(1000); } AssertUtil.ContainsExactly(project.GetPythonProject().ActiveInterpreter.FindModules("flask"), "flask"); } }
public void StartNewAppSameAsProjectName(VisualStudioApp app, DjangoInterpreterSetter interpreterSetter) { var project = app.CreateProject( PythonVisualStudioApp.TemplateLanguageName, PythonVisualStudioApp.DjangoWebProjectTemplate, TestData.GetTempPath(), "StartNewAppSameAsProjectName" ); app.SolutionExplorerTreeView.SelectProject(project); using (var newAppDialog = NewAppDialog.FromDte(app)) { newAppDialog.AppName = app.Dte.Solution.Projects.Item(1).Name; newAppDialog.OK(); } using (var dlg = AutomationDialog.WaitForDialog(app)) { } }
public void WebProjectInstallOnNew() { using (var app = new PythonVisualStudioApp()) { TaskExt.WaitAndUnwrapExceptions( Pip.Uninstall(app.ServiceProvider, app.InterpreterService.DefaultInterpreter, "bottle", false) ); var t = Task.Run(() => app.CreateProject( PythonVisualStudioApp.TemplateLanguageName, PythonVisualStudioApp.BottleWebProjectTemplate, TestData.GetTempPath(), "WebProjectInstallOnNew", suppressUI: false )); using (var dlg = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(t)))) { // Install to active environment dlg.ClickButtonAndClose("CommandLink_1001", nameIsAutomationId: true); } var project = TaskExt.WaitAndUnwrapExceptions(t); var provider = project.Properties.Item("InterpreterFactoryProvider").Value as MSBuildProjectInterpreterFactoryProvider; Assert.AreSame(app.InterpreterService.DefaultInterpreter, provider.ActiveInterpreter); for (int retries = 60; retries > 0; --retries) { if (InterpreterExt.FindModules(provider.ActiveInterpreter, "bottle").Any()) { break; } Thread.Sleep(1000); } AssertUtil.ContainsExactly( InterpreterExt.FindModules(provider.ActiveInterpreter, "bottle"), "bottle" ); TaskExt.WaitAndUnwrapExceptions( Pip.Uninstall(app.ServiceProvider, app.InterpreterService.DefaultInterpreter, "bottle", false) ); } }
public TreeNode AddExistingVirtualEnvironment(EnvDTE.Project project, string envPath, out string envName) { var environmentsNode = OpenSolutionExplorer().FindChildOfProject(project, Strings.Environments); environmentsNode.Select(); using (var createVenv = AutomationDialog.FromDte(this, "Python.AddVirtualEnvironment")) { new TextBox(createVenv.FindByAutomationId("VirtualEnvPath")).SetValue(envPath); var baseInterp = new ComboBox(createVenv.FindByAutomationId("BaseInterpreter")).GetSelectedItemName(); envName = string.Format("{0} ({1})", Path.GetFileName(envPath), baseInterp); Console.WriteLine("Expecting environment named: {0}", envName); createVenv.ClickButtonAndClose("Add", nameIsAutomationId: true); } return(OpenSolutionExplorer().WaitForChildOfProject(project, Strings.Environments, envName)); }
public void DeferredSaveWithDot() { string fullname; using (var app = new PythonVisualStudioApp()) { // http://pytools.codeplex.com/workitem/623 // enable deferred saving on projects var props = app.Dte.get_Properties("Environment", "ProjectsAndSolution"); var prevValue = props.Item("SaveNewProjects").Value; props.Item("SaveNewProjects").Value = false; app.OnDispose(() => { props.Item("SaveNewProjects").Value = prevValue; }); using (var newProjDialog = app.FileNewProject()) { newProjDialog.FocusLanguageNode(); var consoleApp = newProjDialog.ProjectTypes.FindItem("Python Application"); consoleApp.Select(); newProjDialog.ProjectName = "Fob.Oar"; newProjDialog.OK(); } // wait for new solution to load... for (int i = 0; i < 100 && app.Dte.Solution.Projects.Count == 0; i++) { System.Threading.Thread.Sleep(1000); } using (var saveDialog = AutomationDialog.FromDte(app, "File.SaveAll")) { saveDialog.ClickButtonAndClose("Save"); } fullname = app.Dte.Solution.FullName; } try { // Delete the created directory after the solution has been // closed. Directory.Delete(Path.GetDirectoryName(fullname), true); } catch { } }
public void DragDropRelocatedTest(VisualStudioApp app) { var sln = app.CopyProjectForTest(@"TestData\DragDropRelocatedTest.sln"); var slnDir = PathUtils.GetParent(sln); FileUtils.CopyDirectory(TestData.GetPath("TestData", "DragDropRelocatedTest"), Path.Combine(slnDir, "DragDropRelocatedTest")); app.OpenProject(sln); app.OpenSolutionExplorer(); var window = app.SolutionExplorerTreeView; var folder = window.FindItem("Solution 'DragDropRelocatedTest' (1 project)", "DragDropTest", "TestFolder", "SubItem.py"); var point = folder.GetClickablePoint(); Mouse.MoveTo(point); Mouse.Down(MouseButton.Left); var projectItem = window.FindItem("Solution 'DragDropRelocatedTest' (1 project)", "DragDropTest"); point = projectItem.GetClickablePoint(); Mouse.MoveTo(point); Mouse.Up(MouseButton.Left); using (var dlg = AutomationDialog.WaitForDialog(app)) { dlg.OK(); } Assert.IsNotNull(window.WaitForItem("Solution 'DragDropRelocatedTest' (1 project)", "DragDropTest", "SubItem.py")); app.Dte.Solution.Close(true); // Ensure file was moved and the path was updated correctly. var project = app.OpenProject(sln); foreach (var item in project.ProjectItems.OfType <OAFileItem>()) { Assert.IsTrue(File.Exists((string)item.Properties.Item("FullPath").Value), (string)item.Properties.Item("FullPath").Value); } }
public void InstallUninstallPackage() { using (var app = new PythonVisualStudioApp()) using (var dis = Init(app)) { var project = CreateTemporaryProject(app); string envName; var env = app.CreateVirtualEnvironment(project, out envName); env.Select(); using (var installPackage = AutomationDialog.FromDte(app, "Python.InstallPackage")) { var packageName = new TextBox(installPackage.FindByAutomationId("Name")); packageName.SetValue("azure==0.6.2"); installPackage.ClickButtonAndClose("OK", nameIsAutomationId: true); } var azure = app.SolutionExplorerTreeView.WaitForChildOfProject( project, SR.GetString(SR.Environments), envName, "azure (0.6.2)" ); azure.Select(); using (var confirmation = AutomationDialog.FromDte(app, "Edit.Delete")) { confirmation.OK(); } app.SolutionExplorerTreeView.WaitForChildOfProjectRemoved( project, SR.GetString(SR.Environments), envName, "azure (0.6.2)" ); } }
/// <summary> /// Move item to where item exists across project types. /// </summary> private void MoveDuplicateFileNameCrossProjectCSharpSkipMove(VisualStudioApp app, ProjectGenerator pg, MoveDelegate mover) { foreach (var projectType in pg.ProjectTypes) { var projectDefs = new[] { new ProjectDefinition("MoveDuplicateFileName1", projectType, ProjectGenerator.ItemGroup( ProjectGenerator.Content("textfile.txt", "MoveDuplicateFileName1") ) ), new ProjectDefinition("MoveDuplicateFileNameCS", ProjectType.CSharp, ProjectGenerator.ItemGroup( ProjectGenerator.Folder("Folder"), ProjectGenerator.Content("textfile.txt", "MoveDuplicateFileNameCS") ) ) }; using (var solution = SolutionFile.Generate("MoveDuplicateFileName", projectDefs).ToVs(app)) { mover( solution, solution.FindItem("MoveDuplicateFileNameCS"), solution.FindItem("MoveDuplicateFileName1", "textfile.txt") ); // say no to replacing in the C# project system using (var dlg = AutomationDialog.WaitForDialog(app)) { dlg.ClickButtonAndClose("No"); } solution.AssertFileExistsWithContent("MoveDuplicateFileName1", "MoveDuplicateFileName1", "textfile.txt"); solution.AssertFileExistsWithContent("MoveDuplicateFileNameCS", "MoveDuplicateFileNameCS", "textfile.txt"); } } }
public void TestLongPathCheck() { string[] expectedLongPaths = { @"node_modules\azure\node_modules\azure-common\node_modules\xml2js\node_modules\sax\test\trailing-attribute-no-value.js", @"node_modules\azure\node_modules\azure-common\node_modules\xml2js\node_modules\sax\test\xmlns-xml-default-prefix-attribute.js", @"node_modules\azure\node_modules\azure-common\node_modules\xml2js\node_modules\sax\test\xmlns-xml-default-redefine.js", @"node_modules\azure\node_modules\request\node_modules\form-data\node_modules\combined-stream\node_modules", @"node_modules\azure\node_modules\request\node_modules\http-signature\node_modules\ctype\tst\ctio\uint\tst.roundtrip.js", }; string projectDir = CreateTempPathOfLength(248 - 1 - expectedLongPaths.Min(s => s.Length)); try { foreach (var fileName in new[] { "HelloWorld.njsproj", "HelloWorld.sln", "package.json", "README.md", "server.js" }) { File.Copy(TestData.GetPath(@"TestData\HelloWorld\" + fileName), projectDir + "\\" + fileName); } using (var app = new NodejsVisualStudioApp()) { try { NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths = true; var project = app.OpenProject(projectDir + "\\HelloWorld.sln"); // Wait for new solution to load. for (int i = 0; i < 40 && app.Dte.Solution.Projects.Count == 0; i++) { System.Threading.Thread.Sleep(250); } const string interpreterDescription = "Node.js Interactive Window"; app.Dte.ExecuteCommand("View.Node.jsInteractiveWindow"); var interactive = app.GetInteractiveWindow(interpreterDescription); if (interactive == null) { Assert.Inconclusive("Need " + interpreterDescription); } interactive.WaitForIdleState(); var npmTask = interactive.ReplWindow.ExecuteCommand(".npm install [email protected]"); using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(npmTask)))) { // The option to offer "npm dedupe" should be there. var firstCommandLink = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(firstCommandLink); Assert.IsTrue(firstCommandLink.Current.Name.Contains("npm dedupe")); dialog.ClickButtonByAutomationId("ExpandoButton"); var detailsText = dialog.FindByAutomationId("ExpandedFooterTextLink"); Assert.IsNotNull(detailsText); var reportedLongPaths = (from line in detailsText.Current.Name.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) where line.StartsWith("•") let nbspIndex = line.IndexOf('\u00A0') where nbspIndex >= 0 select line.Substring(1, nbspIndex - 1).Trim() ).ToArray(); Console.WriteLine("Reported paths:"); foreach (var path in reportedLongPaths) { Console.WriteLine("\t" + path); } reportedLongPaths = reportedLongPaths.Except(expectedLongPaths).ToArray(); if (reportedLongPaths.Length != 0) { Console.WriteLine("Unexpected paths:"); foreach (var path in reportedLongPaths) { Console.WriteLine("\t" + path); } Assert.Fail("Unexpected long paths reported."); } dialog.WaitForClosed(TimeSpan.FromSeconds(1), () => { // Click the first command button (dedupe). firstCommandLink.SetFocus(); Keyboard.Press(System.Windows.Input.Key.Enter); }); } // Clicking on that button should not change the option. Assert.IsTrue(NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths); interactive.WaitForTextContainsAll("dedupe successfully completed"); interactive.WaitForIdleState(); // npm dedupe won't be able to fix the problem, so we should get the dialog once again. using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(npmTask)))) { // The option to offer "npm dedupe" should not be there anymore. var firstCommandLink = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(firstCommandLink); Assert.IsFalse(firstCommandLink.Current.Name.Contains("npm dedupe")); dialog.WaitForClosed(TimeSpan.FromSeconds(1), () => { Keyboard.Type("\r"); // click the first command button (do nothing, but warn next time) }); } npmTask.Wait(1000); Assert.IsTrue(npmTask.IsCompleted); // Clicking on that button should not change the option. Assert.IsTrue(NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths); // Try again to see that the dialog still appears. Any npm command triggers the check. // and since we didn't do anything to fix the problem, we should still get the dialog. interactive.WaitForIdleState(); npmTask = interactive.ReplWindow.ExecuteCommand(".npm list"); using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(app.WaitForDialog(npmTask)))) { // The option to offer "npm dedupe" should be there again, since this is a new check. var firstCommandLink = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(firstCommandLink); Assert.IsTrue(firstCommandLink.Current.Name.Contains("npm dedupe")); dialog.WaitForClosed(TimeSpan.FromSeconds(1), () => { // Click the third command button (do nothing, do not warn anymore) firstCommandLink.SetFocus(); Keyboard.Press(System.Windows.Input.Key.Tab); Keyboard.Press(System.Windows.Input.Key.Tab); Keyboard.Press(System.Windows.Input.Key.Enter); }); } npmTask.Wait(1000); Assert.IsTrue(npmTask.IsCompleted); // Clicking on that button should change the option to false. Assert.IsFalse(NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths); // Try again to see that the dialog does not appear anymore. interactive.WaitForIdleState(); npmTask = interactive.ReplWindow.ExecuteCommand(".npm list"); app.WaitForNoDialog(TimeSpan.FromSeconds(3)); } finally { NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths = true; } } } finally { DeleteLongPath(projectDir); } }
public void CustomCommandsRequiredPackages() { using (var app = new PythonVisualStudioApp()) using (var dis = app.SelectDefaultInterpreter(PythonVersion, "virtualenv")) { PythonProjectNode node; EnvDTE.Project proj; OpenProject(app, "CommandRequirePackages.sln", out node, out proj); string envName; var env = app.CreateVirtualEnvironment(proj, out envName); env.Select(); app.Dte.ExecuteCommand("Python.ActivateEnvironment"); // Ensure that no error dialog appears app.WaitForNoDialog(TimeSpan.FromSeconds(5.0)); // First, execute the command and cancel it. var task = ExecuteAsync(node, "Require Packages"); try { var dialogHandle = app.WaitForDialog(task); if (dialogHandle == IntPtr.Zero) { if (task.IsFaulted && task.Exception != null) { Assert.Fail("Unexpected exception in package install confirmation dialog:\n{0}", task.Exception); } else { Assert.AreNotEqual(IntPtr.Zero, dialogHandle); } } using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(dialogHandle))) { var label = dialog.FindByAutomationId("CommandLink_1000"); Assert.IsNotNull(label); string expectedLabel = "The following packages will be installed using pip:\r\n" + "\r\n" + "ptvsd\r\n" + "azure==0.1";; Assert.AreEqual(expectedLabel, label.Current.HelpText); dialog.Cancel(); try { task.Wait(1000); Assert.Fail("Command was not canceled after dismissing the package install confirmation dialog"); } catch (AggregateException ex) { if (!(ex.InnerException is TaskCanceledException)) { throw; } } } } finally { if (!task.IsCanceled && !task.IsCompleted && !task.IsFaulted) { if (task.Wait(10000)) { task.Dispose(); } } else { task.Dispose(); } } // Then, execute command and allow it to proceed. task = ExecuteAsync(node, "Require Packages"); try { var dialogHandle = app.WaitForDialog(task); if (dialogHandle == IntPtr.Zero) { if (task.IsFaulted && task.Exception != null) { Assert.Fail("Unexpected exception in package install confirmation dialog:\n{0}", task.Exception); } else { Assert.AreNotEqual(IntPtr.Zero, dialogHandle); } } using (var dialog = new AutomationDialog(app, AutomationElement.FromHandle(dialogHandle))) { dialog.ClickButtonAndClose("CommandLink_1000", nameIsAutomationId: true); } task.Wait(); var ver = PythonVersion.Version.ToVersion(); ExpectOutputWindowText(app, string.Format("pass {0}.{1}", ver.Major, ver.Minor)); } finally { if (!task.IsCanceled && !task.IsCompleted && !task.IsFaulted) { if (task.Wait(10000)) { task.Dispose(); } } else { task.Dispose(); } } } }
public TreeNode CreateVirtualEnvironment(EnvDTE.Project project, out string envName, out string envPath) { var environmentsNode = OpenSolutionExplorer().FindChildOfProject(project, Strings.Environments); environmentsNode.Select(); using (var pss = new ProcessScope("python")) { using (var createVenv = AutomationDialog.FromDte(this, "Python.AddVirtualEnvironment")) { envPath = new TextBox(createVenv.FindByAutomationId("VirtualEnvPath")).GetValue(); var baseInterp = new ComboBox(createVenv.FindByAutomationId("BaseInterpreter")).GetSelectedItemName(); var baseConfig = ComponentModel.GetService <IInterpreterRegistryService>().Configurations .FirstOrDefault(c => c.FullDescription == baseInterp); if (baseConfig == null) { envName = "{0} ({1})".FormatUI(envPath, baseInterp); } else { envName = "{0} {1} {2} ({3})".FormatUI( envPath, baseConfig.Architecture == System.Reflection.ProcessorArchitecture.Amd64 ? "64-bit" : "32-bit", baseConfig.Version, baseInterp ); } Console.WriteLine("Expecting environment named: {0}", envName); // Force a wait for the view to be updated. var wnd = (DialogWindowVersioningWorkaround)HwndSource.FromHwnd( new IntPtr(createVenv.Element.Current.NativeWindowHandle) ).RootVisual; wnd.Dispatcher.Invoke(() => { var view = (AddVirtualEnvironmentView)wnd.DataContext; return(view.UpdateInterpreter(view.BaseInterpreter)); }).Wait(); createVenv.ClickButtonByAutomationId("Create"); createVenv.ClickButtonAndClose("Close", nameIsAutomationId: true); } var nowRunning = pss.WaitForNewProcess(TimeSpan.FromMinutes(1)); if (nowRunning == null || !nowRunning.Any()) { Assert.Fail("Failed to see python process start to create virtualenv"); } foreach (var p in nowRunning) { if (p.HasExited) { continue; } try { p.WaitForExit(30000); } catch (Win32Exception ex) { Console.WriteLine("Error waiting for process ID {0}\n{1}", p.Id, ex); } } } try { return(OpenSolutionExplorer().WaitForChildOfProject(project, Strings.Environments, envName)); } finally { var text = GetOutputWindowText("General"); if (!string.IsNullOrEmpty(text)) { Console.WriteLine("** Output Window text"); Console.WriteLine(text); Console.WriteLine("***"); Console.WriteLine(); } } }
public TreeNode CreateVirtualEnvironment(EnvDTE.Project project, out string envName, out string envPath) { var environmentsNode = OpenSolutionExplorer().FindChildOfProject( project, SR.GetString(SR.Environments) ); environmentsNode.Select(); var alreadyRunning = new HashSet <int>(Process.GetProcessesByName("python").Select(p => p.Id)); using (var createVenv = AutomationDialog.FromDte(this, "Python.AddVirtualEnvironment")) { envPath = new TextBox(createVenv.FindByAutomationId("VirtualEnvPath")).GetValue(); var baseInterp = new ComboBox(createVenv.FindByAutomationId("BaseInterpreter")).GetSelectedItemName(); envName = string.Format("{0} ({1})", envPath, baseInterp); Console.WriteLine("Expecting environment named: {0}", envName); // Force a wait for the view to be updated. var wnd = (DialogWindowVersioningWorkaround)HwndSource.FromHwnd( new IntPtr(createVenv.Element.Current.NativeWindowHandle) ).RootVisual; wnd.Dispatcher.Invoke(() => { var view = (AddVirtualEnvironmentView)wnd.DataContext; return(view.UpdateInterpreter(view.BaseInterpreter)); }).Wait(); createVenv.ClickButtonByAutomationId("Create"); createVenv.ClickButtonAndClose("Close", nameIsAutomationId: true); } List <Process> nowRunning = null; for (int retries = 100; retries > 0 && (nowRunning == null || !nowRunning.Any()); --retries) { System.Threading.Thread.Sleep(100); nowRunning = Process.GetProcessesByName("python").Where(p => !alreadyRunning.Contains(p.Id)).ToList(); } if (nowRunning == null || !nowRunning.Any()) { Assert.Fail("Failed to see python process start to create virtualenv"); } foreach (var p in nowRunning) { if (p.HasExited) { continue; } try { p.WaitForExit(30000); } catch (Win32Exception ex) { Console.WriteLine("Error waiting for process ID {0}\n{1}", p.Id, ex); } } return(OpenSolutionExplorer().WaitForChildOfProject( project, SR.GetString(SR.Environments), envName )); }