private async Task Connect( string application, string executable, Version version, string hive, CancellationToken cancel ) { Close(); Internal.VisualStudio ide = null; try { ide = await Internal.VisualStudio.LaunchAsync(application, executable, version, hive, cancel); var p = Process.GetProcessById(ide.ProcessId); string url = string.Format( "ipc://{0}/{1}", Internal.VSTestHostPackage.GetChannelName(Process.GetProcessById(ide.ProcessId)), TesteeTestAdapter.Url ); _remote = (TesteeTestAdapter)RemotingServices.Connect(typeof(TesteeTestAdapter), url); _ide = ide; ide = null; } finally { if (ide != null) { ide.Dispose(); } } }
private async Task Connect( string application, string executable, Version version, string hive, IRunContext runContext, ITestElement currentTest, CancellationToken cancel ) { var hiveOption = string.IsNullOrEmpty(hive) ? "" : (" /rootSuffix " + hive); if (_ide != null && _remote != null && application == _currentApplication && executable == _currentExecutable && version == _currentVersion && hive == _currentHive) { if (runContext != null) { SendMessage( runContext, string.Format(Resources.VSReuseMessage, application, executable, version, hiveOption), currentTest ); } return; } Close(); if (runContext != null) { SendMessage( runContext, string.Format(Resources.VSLaunchMessage, application, executable, version, hiveOption), currentTest ); } Internal.VisualStudio ide = null; try { ide = await Internal.VisualStudio.LaunchAsync(application, executable, version, hive, cancel); var p = Process.GetProcessById(ide.ProcessId); var url = string.Format("ipc://{0}/{1}", VSTestHostPackage.GetChannelName(p), TesteeTestAdapter.Url); try { _remote = (TesteeTestAdapter)RemotingServices.Connect(typeof(TesteeTestAdapter), url); } catch (RemotingException ex) { throw new InvalidOperationException(Resources.FailedToConnect, ex); } _currentApplication = application; _currentExecutable = executable; _currentVersion = version; _currentHive = hive; _ide = ide; ide = null; } finally { if (ide != null) { ide.Dispose(); } } }
/// <summary> /// Implements initialization. This is called by ITestAdapter.Initialize /// (a synchronous function) which will block until this function is /// completed. /// </summary> /// <param name="runContext"> /// The context for the current test run. /// </param> private async Task InitializeWorker(IRunContext runContext) { string application, executable, versionString, hive; Version version; string launchTimeoutInSecondsString; int launchTimeoutInSeconds; var vars = runContext.RunConfig.TestRun.RunConfiguration.TestSettingsProperties; // VSApplication is the registry key name like 'VisualStudio' vars.TryGetValue("VSApplication", out application); // VSExecutableName is the executable name like 'devenv' if (vars.TryGetValue("VSExecutable", out executable) && !string.IsNullOrEmpty(executable) && string.IsNullOrEmpty(Path.GetExtension(executable))) { executable = Path.ChangeExtension(executable, ".exe"); } // VSVersion is the version like '12.0' if (!vars.TryGetValue("VSVersion", out versionString) || !Version.TryParse(versionString, out version)) { version = null; } // VSHive is the optional hive like 'Exp' vars.TryGetValue("VSHive", out hive); if (!vars.TryGetValue("VSLaunchTimeoutInSeconds", out launchTimeoutInSecondsString) || !int.TryParse(launchTimeoutInSecondsString, out launchTimeoutInSeconds)) { launchTimeoutInSeconds = 30; } if (string.IsNullOrEmpty(application) || string.IsNullOrEmpty(executable) || version == null) { throw new ArgumentException(string.Format( Resources.MissingConfigurationValues, application ?? "(null)", executable ?? "(null)", version != null ? version.ToString() : "(null)", hive ?? "(null)" )); } if (application == "Mock") { _runContext = runContext; _remote = new TesteeTestAdapter(); _remote.Initialize(_runContext); // In the mock case tester and testee are the same process, therefore // VSTestContext is in our process too. So we can just set this value // directly here. VSTestContext.IsMock = true; _mockVs = true; return; } // TODO: Detect and perform first run of VS if necessary. // The first time a VS hive is run, the user sees a dialog allowing // them to select settings such as the theme. We can avoid this by // running devenv.exe /resetSettings <path to profile.settings> // first, though it is not trivial to detect when this is necessary. // Without having done this, all tests will time out. For now, the // user is responsible for running VS at least once before // attempting to execute tests. var cts = new CancellationTokenSource(TimeSpan.FromSeconds(launchTimeoutInSeconds)); try { await Connect(application, executable, version, hive, cts.Token); } catch (OperationCanceledException ex) { throw new TimeoutException(string.Format(Resources.VSLaunchTimeout, launchTimeoutInSeconds), ex); } _runContext = runContext; _remote.Initialize(_runContext); if (_runContext.RunConfig.TestRun.RunConfiguration.IsExecutedUnderDebugger) { // If we're debugging, tell our host VS to attach to the new VS // instance we just started. bool mixedMode = false; string debugMixedMode; if (!vars.TryGetValue("VSDebugMixedMode", out debugMixedMode) || !bool.TryParse(debugMixedMode, out mixedMode)) { mixedMode = false; } TesterDebugAttacherShared.AttachDebugger(_ide.ProcessId, mixedMode); } }
/// <summary> /// Implements initialization. This is called by ITestAdapter.Initialize /// (a synchronous function) which will block until this function is /// completed. /// </summary> /// <param name="runContext"> /// The context for the current test run. /// </param> private async Task InitializeWorker( TestProperties vars, IRunContext runContext, ITestElement currentTest = null ) { string application, executable, versionString, hive; Version version; string launchTimeoutInSecondsString; int launchTimeoutInSeconds; // VSApplication is the registry key name like 'VisualStudio' application = vars[VSTestProperties.VSApplication.Key] ?? VSTestProperties.VSApplication.VisualStudio; // VSExecutableName is the executable name like 'devenv' if (!vars.TryGetValue(VSTestProperties.VSExecutable.Key, out executable)) { executable = VSTestProperties.VSExecutable.DevEnv; } if (!string.IsNullOrEmpty(executable) && string.IsNullOrEmpty(Path.GetExtension(executable))) { executable = Path.ChangeExtension(executable, ".exe"); } // VSVersion is the version like '12.0' if (!vars.TryGetValue(VSTestProperties.VSVersion.Key, out versionString) || !Version.TryParse(versionString, out version)) { version = new Version(int.Parse(AssemblyVersionInfo.VSVersion), 0); } // VSHive is the optional hive like 'Exp' hive = vars[VSTestProperties.VSHive.Key]; if (!vars.TryGetValue(VSTestProperties.VSLaunchTimeoutInSeconds.Key, out launchTimeoutInSecondsString) || !int.TryParse(launchTimeoutInSecondsString, out launchTimeoutInSeconds)) { launchTimeoutInSeconds = 30; } if (string.IsNullOrEmpty(application) || string.IsNullOrEmpty(executable) || version == null) { throw new ArgumentException(string.Format( Resources.MissingConfigurationValues, application ?? "(null)", executable ?? "(null)", version != null ? version.ToString() : "(null)", hive ?? "(default)" )); } _mockVs = (application == VSTestProperties.VSApplication.Mock); if (_mockVs) { _remote = new TesteeTestAdapter(); _remote.Initialize(_runContext); // In the mock case tester and testee are the same process, therefore // VSTestContext is in our process too. So we can just set this value // directly here. VSTestContext.IsMock = true; return; } // TODO: Detect and perform first run of VS if necessary. // The first time a VS hive is run, the user sees a dialog allowing // them to select settings such as the theme. We can avoid this by // running devenv.exe /resetSettings <path to profile.settings> // first, though it is not trivial to detect when this is necessary. // Without having done this, all tests will time out. For now, the // user is responsible for running VS at least once before // attempting to execute tests. var cts = new CancellationTokenSource(TimeSpan.FromSeconds(launchTimeoutInSeconds)); try { await Connect(application, executable, version, hive, runContext, currentTest, cts.Token); } catch (OperationCanceledException ex) { throw new TimeoutException(string.Format(Resources.VSLaunchTimeout, launchTimeoutInSeconds), ex); } catch (Exception ex) { throw new InvalidOperationException( string.Format(Resources.VSFailedToLaunch, application, executable, version, hive), ex ); } }