簡體   English   中英

Visual Studio Unittest適配器:如何在執行程序中檢測活動配置

[英]Visual Studio Unittest Adapter: how to detect active configuration in executor

我知道我可以使用dte對象獲得當前的活動配置( Debug|Release|... ):

using Microsoft.VisualStudio.Shell;
using EnvDTE;
using EnvDTE80;    

public static string GetCurrentActiveConfiguration()
{    
  var dte = (DTE2) ServiceProvider.GlobalProvider.GetService(typeof (DTE));
  var p = dte?.Solution.SolutionBuild;
  var sc = p?.ActiveConfiguration;
  return sc.Name;
}

在我的單元測試適配器的測試發現步驟中,這很好用。

但是,TestExecutor( Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter.ITestExecutor )作為單獨的進程vstest.executionengine.x86.exe運行,因此,我似乎無法訪問有關Visual Studio實例的任何信息。

如何從RunTests方法中確定當前的活動配置? RunTests的簽名是:

public void RunTests(IEnumerable<string> sources, IRunContext runContext, IFrameworkHandle frameworkHandle)
public void RunTests(IEnumerable<TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle)

似乎我並不是唯一需要以下信息的人:

需要根據所使用的Visual Studio版本進行一些調整,但是可以很清楚地理解該機制。

using EnvDTE;
using System;
using System.Management;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text.RegularExpressions;

namespace ImplemenationCTestTestAdapter
{
    /// <remarks>
    ///  Taken from here: https://github.com/getgauge/gauge-visualstudio/blob/master/Gauge.VisualStudio/Helpers/DTEHelper.cs
    ///         and here: https://github.com/smkanadl/CTestTestAdapter/blob/master/ImplemenationCTestTestAdapter/DTEHelper.cs
    /// </remarks>
    internal static class DteHelper
    {
        [DllImport("ole32.dll")]
        private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

        private static readonly Regex DteRegex = new Regex(@"!\S+\.DTE\.[\d\.]+:\d+");

        internal static DTE GetCurrent(IServiceProvider serviceProvider = null)
        {
            if (serviceProvider != null)
            {
                return (DTE) serviceProvider.GetService(typeof (DTE));
            }
            var currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            var vsProcessId = GetVisualStudioProcessId(currentProcess.Id);
            object runningObject = null;
            IBindCtx bindCtx = null;
            IRunningObjectTable rot = null;
            IEnumMoniker enumMonikers = null;
            try
            {
                Marshal.ThrowExceptionForHR(CreateBindCtx(0, out bindCtx));
                bindCtx.GetRunningObjectTable(out rot);
                rot.EnumRunning(out enumMonikers);
                var moniker = new IMoniker[1];
                var numberFetched = IntPtr.Zero;
                while (enumMonikers.Next(1, moniker, numberFetched) == 0)
                {
                    var runningObjectMoniker = moniker[0];
                    string name = null;
                    try
                    {
                        runningObjectMoniker?.GetDisplayName(bindCtx, null, out name);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // do nothing.
                    }
                    if (string.IsNullOrEmpty(name) || !DteRegex.IsMatch(name))
                    {
                        continue;
                    }
                    if (!name.EndsWith(vsProcessId.ToString()))
                    {
                        continue;
                    }
                    rot.GetObject(runningObjectMoniker, out runningObject);
                    break;
                }
            }
            finally
            {
                if (enumMonikers != null)
                {
                    Marshal.ReleaseComObject(enumMonikers);
                }
                if (rot != null)
                {
                    Marshal.ReleaseComObject(rot);
                }
                if (bindCtx != null)
                {
                    Marshal.ReleaseComObject(bindCtx);
                }
            }
            return (DTE) runningObject;
        }

        private static int GetVisualStudioProcessId(int testRunnerProcessId)
        {
            var mos =
                new ManagementObjectSearcher($"Select * From Win32_Process Where ProcessID={testRunnerProcessId}");
            var processes =
                mos.Get().Cast<ManagementObject>().Select(mo => Convert.ToInt32(mo["ParentProcessID"])).ToList();
            if (processes.Any())
            {
                return processes.First();
            }
            return -1;
        }
    }
}

ManagementObjectSearcher包含在程序集System.Management 您需要添加相應的參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM