[英]How do I get the projects to build in the active Visual Studio configuration?
[英]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.