static GlobalServices() { try { var dte = RunningObjects.GetDTE(TimeSpan.FromSeconds(5)); if (dte == null) { Debug.Fail(Strings.GlobalServices.NoDte); s_tracer.TraceEvent(TraceEventType.Warning, 0, Strings.GlobalServices.NoDte); Instance = new NullServices(); } else { Instance = new OleServiceProvider(dte); s_tracer.TraceInformation(Strings.GlobalServices.InitializedDte(dte.Version)); } } catch (NotSupportedException ex) { Debug.Fail(Strings.GlobalServices.NoDte); s_tracer.TraceEvent(TraceEventType.Warning, 0, Strings.GlobalServices.NoDte + Environment.NewLine + ex.ToString()); Instance = new NullServices(); } }
private bool Start() { _pipeName = Guid.NewGuid().ToString(); var info = new ProcessStartInfo(_devEnvPath, string.IsNullOrEmpty(_rootSuffix) ? "" : "/RootSuffix " + _rootSuffix) { UseShellExecute = false, WorkingDirectory = Directory.GetCurrentDirectory(), }; // This environment variable is used by the VsRemoveRunner to set up the right // server channel named pipe, which is later used by the test runner to execute // tests in the VS app domain. info.EnvironmentVariables.Add(Constants.PipeNameEnvironmentVariable, _pipeName); info.EnvironmentVariables.Add(Constants.BaseDirectoryEnvironmentVariable, Directory.GetCurrentDirectory()); // Allow debugging xunit.vsix itself by setting the `xunit.vsix.debug=true` envvar in the current VS. info.EnvironmentVariables.Add(Constants.DebugEnvironmentVariable, Environment.GetEnvironmentVariable(Constants.DebugEnvironmentVariable)); // Propagate profiling values to support OpenCover or any third party profiler // already attached to the current process. PropagateProfilingVariables(info); Constants.Tracer.TraceEvent(TraceEventType.Verbose, 0, Strings.VsClient.RunnerEnvVars(string.Join(Environment.NewLine, Environment .GetEnvironmentVariables() .OfType <DictionaryEntry>() .OrderBy(x => (string)x.Key) .Where(x => !((string)x.Key).Equals("path", StringComparison.OrdinalIgnoreCase) && !((string)x.Key).Equals("pathbackup", StringComparison.OrdinalIgnoreCase)) .Select(x => " " + x.Key + "=" + x.Value)))); // Eat the standard output to prevent this from polluting AppVeyor or other CI systems // that capture processes standard output. info.RedirectStandardOutput = true; info.RedirectStandardInput = true; info.RedirectStandardError = true; Process = Process.Start(info); // This forces us to wait until VS is fully started. var dte = RunningObjects.GetDTE(_visualStudioVersion, Process.Id, TimeSpan.FromSeconds(_settings.StartupTimeout)); if (dte == null) { return(false); } var services = new OleServiceProvider(dte); IVsShell shell; while ((shell = (IVsShell)services.GetService(typeof(SVsShell))) == null) { Thread.Sleep(_settings.RetrySleepInterval); } object zombie; while ((int?)(zombie = shell.GetProperty((int)__VSSPROPID.VSSPROPID_Zombie, out zombie)) != 0) { Thread.Sleep(_settings.RetrySleepInterval); } // Retrieve the component model service, which could also now take time depending on new // extensions being installed or updated before the first launch. var components = services.GetService <SComponentModel, object>(); if (Debugger.IsAttached) { // When attached via TD.NET, there will be an environment variable named DTE_MainWindow=2296172 var mainWindow = Environment.GetEnvironmentVariable("DTE_MainWindow"); if (!string.IsNullOrEmpty(mainWindow)) { var attached = false; var retries = 0; var sleep = _settings.RetrySleepInterval; while (retries++ < _settings.DebuggerAttachRetries && !attached) { try { var mainHWnd = int.Parse(mainWindow); var mainDte = GetAllDtes().FirstOrDefault(x => x.MainWindow.HWnd == mainHWnd); if (mainDte != null) { var startedVs = mainDte.Debugger.LocalProcesses.OfType <EnvDTE.Process>().FirstOrDefault(x => x.ProcessID == Process.Id); if (startedVs != null) { startedVs.Attach(); attached = true; break; } } } catch (Exception ex) { s_tracer.TraceEvent(TraceEventType.Warning, 0, Strings.VsClient.RetryAttach(retries, _settings.DebuggerAttachRetries) + Environment.NewLine + ex.ToString()); } Thread.Sleep(sleep); sleep = sleep * retries; } if (!attached) { s_tracer.TraceEvent(TraceEventType.Error, 0, Strings.VsClient.FailedToAttach(_visualStudioVersion, _rootSuffix)); } } } try { Injector.Launch(Process.MainWindowHandle, GetType().Assembly.Location, typeof(VsStartup).FullName, $"Start"); } catch (Exception ex) { s_tracer.TraceEvent(TraceEventType.Error, 0, Strings.VsClient.FailedToInject(Process.Id) + Environment.NewLine + ex.ToString()); return(false); } return(true); }