【问题标题】:Locate MSTest.exe using powershell使用 powershell 找到 MSTest.exe
【发布时间】:2016-02-09 20:28:01
【问题描述】:

我正在自动化我的 .Net 解决方案构建以完全在 PowerShell 中。我想使用 PowerShell 定位 MSTest.exe。

我用下面的脚本来定位MSBuild.exe,希望能有类似的东西来定位MSTest.exe

$msBuildQueryResult = reg.exe query "HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0" /v MSBuildToolsPath
$msBuildQueryResult = $msBuildQueryResult[2]
$msBuildQueryResult = $msBuildQueryResult.Split(" ")
$msBuildLocation = $msBuildQueryResult[12] + "MSBuild.exe"

有什么路线吗?

【问题讨论】:

  • 您不需要在 PowerShell 中使用 reg.exe。您可以使用Get-ItemProperty 检索注册表值(属性)。除此之外,还有什么方向?
  • 另外,您是否尝试过 Get-Command MSTest.exe
  • @EBGreen Get-Command MSTest.exe 对我不起作用。
  • @Bill_Stewart 我要获取MSTest.exe的安装路径
  • 你的意思是Get-ChildItem C:\* -Filter MSTest.exe -Recurse

标签: powershell mstest jenkins-mstest


【解决方案1】:

以下适用于 Visual Studio 2010 及更高版本[1]

# Get the tools folder location:

# Option A: Target the *highest version installed*:
$vsToolsDir = (
  Get-Item env:VS*COMNTOOLS | Sort-Object {[int]($_.Name -replace '[^\d]')}
)[-1].Value

# Option B: Target a *specific version*; e.g., Visual Studio 2010,
# internally known as version 10.0.
# (See https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History)
$vsToolsDir = $env:VS100COMNTOOLS

# Now locate msbuild.exe in the "IDE" sibling folder.
$msTestExe = Convert-Path -EA Stop (Join-Path $vsToolsDir '..\IDE\MSTest.exe')

该方法基于this answer,并已推广并适用于 PowerShell。

  • 它基于系统环境变量VS*COMNTOOLS,由 Visual Studio 安装程序创建,其中* 表示 VS 版本号(例如,100 用于 VS 2010)。

    • Re 选项 A:Sort-Object 用于确保最新 Visual Studio 安装是目标,如果多个安装并排安装:
      • 用于排序的脚本块首先仅从变量名中提取嵌入的版本号($_.Name -replace '[^\d]';例如,100 来自VS100COMNTOOLS)并将结果转换为整数([int]); [-1] 然后从排序后的数组中提取最后一个元素 - 即名称具有最高嵌入式版本号的变量对象 - 并访问其值 (.Value)。
  • MSTest.exe 所在的IDE 子文件夹是VS*COMNTOOLS 指向的工具文件夹的兄弟 文件夹。

  • 如果MSTest.exe 不在预期位置,Convert-Path 默认会抛出非终止错误;添加-EA Stop(缩写:-ErrorAction Stop)可确保脚本中止


[1]
- 我已经尝试了 Visual Studio 2015;请让我知道它是否适用于更高版本。
- 可能也适用于 VS 2008。


【讨论】:

    【解决方案2】:

    也许你想要这样的东西?

    $regPath = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0"
    $regValueName = "MSBuildToolsPath"
    $msBuildFilename = "MSBUild.exe"
    if ( Test-Path $regPath ) {
      $toolsPath = (Get-ItemProperty $regPath).$regValueName
      if ( $toolsPath ) {
        $msBuild = Join-Path $toolsPath $msBuildFilename
        if ( -not (Test-Path $msBuild -PathType Leaf) ) {
          Write-Error "File not found - '$msBuild'"
        }
      }
    }
    # Full path and filename of MSBuild.exe in $msBuild variable
    

    【讨论】:

    • 感谢您的代码。我的代码也是这样。我正在寻找类似的代码来定位 MSTest.exe
    【解决方案3】:

    我获取 mstest 路径的方式。 GetMSTestPath 函数是您调用的主函数,然后如果第一个 GetMsTestPathFromVswhere 函数会找到它返回路径的东西,如果不是,您将长时间搜索 mstest.exe。通常,大约需要 10 秒。我知道这不是最好的,但至少当你很难找到 mstest.exe 时它是这样的。希望它对某人有所帮助。 :)))

     function GetMSTestPath
        {
            function GetTime()
            {
                $time_now = Get-Date -format "HH:mm:ss"
                return $time_now;
            }
            function GetMsTestPathFromVswhere {
                $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
                $path = & $vswhere -latest -prerelease -products * -requires Microsoft.Component.MSBuild -property installationPath
                #write-host $path
                if ($path) {
                    $tool = join-path $path 'Common7\IDE\MSTest.exe'
                    if (test-path $tool) {
                        return $tool
                    }
                    return ""
                }
            }
    
            function SeachForMsTestPath
            {
    
                write-host $(GetTime)
                $path =  Get-ChildItem C:\ -Filter MSTest.exe -Recurse -ErrorAction Ignore | ? { $_.VersionInfo.FileDescription -eq 'Test Execution Command Line Tool' } | Select -First 1
                write-host $(GetTime)
                return $path
            }
    
            $msTestExePath = GetMsTestPathFromVswhere
            if ([string]::IsNullOrEmpty($msTestExePath))
            {
                $msTestExePath = SeachForMsTestPath;
                if ([string]::IsNullOrEmpty($msTestExePath))
                {
                    Write-host "MsTest path is not found. Exiting with error"
                    Exit -1
                }
            }
            return $msTestExePath;
        }
    

    【讨论】:

      【解决方案4】:

      感谢@Bill_Stewart,我用你的 cmets 编写了这个工作函数:

      function Get-MSTest-Location {
          $msTests = @()
          $searchResults = Get-ChildItem C:\* -Filter MSTest.exe -Recurse -ErrorAction Ignore
          foreach($searchResult in $searchResults) {
              try{ 
                  if(($searchResult.VersionInfo -ne $null) -and ($searchResult.VersionInfo.FileDescription -eq "Test Execution Command Line Tool"))
                  { $msTests = $msTests + $searchResult.FullName }
              }
              catch{}
              }
          if($msTests.Length -eq 0)
          {return "MSTest not found."}
          return $msTests[0]
      }
      

      【讨论】:

      • 虽然这可行,但效率低下且速度慢 - 我建议探索我的基于环境变量的方法。至于您的命令:您可以将其表示为单个管道:Get-ChildItem C:\ -Filter MSTest.exe -Recurse -ErrorAction Ignore | ? { $_.VersionInfo.FileDescription -eq 'Test Execution Command Line Tool' } | Select -First 1。在 PS v3+ 中,由于流水线优化,使用Select -First 1 也会显着加快命令速度。
      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      • 2017-09-07
      相关资源
      最近更新 更多