예제 #1
0
 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();
     }
 }
예제 #2
0
        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);
        }