如何从 BAT 文件调用 Visual Studio 2017 RC 版本的 MSBuild?

How do I call Visual Studio 2017 RC's version of MSBuild from a BAT file?

早期版本的 MSBuild 可以在这里找到:%programfiles(x86)%\msbuild\<version>\bin\msbuild.exe.

但对于 Visual Studio 2017RC,路径是 %programfiles(x86)%\Microsoft Visual Studio17\Enterprise\MSBuild.0\Bin\msbuild.exe。安装类型:企业、社区或专业,似乎是路径的一部分。这使得很难在 BAT 文件中指定正确的 msbuild 路径,该文件应该可以在具有不同版本 Visual Studio 2017 的许多不同计算机上运行。

从 bat 文件调用 Visual Studio 2017 RC 版本的 Msbuild 的最佳方法是什么?还是来自 PowerShell?

支持的方式

VS2017 的安装引擎有一个互操作 API,允许您查询有关安装了哪些 VS2017 实例的信息。有一个NuGet package for it, and even a sample如何查询,包括安装路径。对于批处理或 PS 文件中的消费,您可能只需重写示例应用程序并从您的脚本中调用它以输出您需要的信息。

不支持的方式

VS 安装引擎将其数据存储在 %ProgramData%\Microsoft\VisualStudio\Packages\_Instances 下。每个 VS2017 实例都有一个文件夹,在该文件夹内有一个 state.json 文件,其中包含有关该安装的信息,包括安装路径。

由于您需要从 .json 文件中提取信息,您可以选择编写一个从脚本文件调用的应用程序,或者直接在脚本中提出一些解析逻辑. 这显然很脆弱,因为 JSON 模式或文件位置可能会改变。

暴力法

假设你使用的是默认安装路径,你可以在%ProgramFiles(x86)%\Microsoft Visual Studio\下递归搜索msbuild.exe(好像会有32位和64位的msbuild.exe对于每个 VS 实例)。这可能是在您的脚本文件中最容易做到的,但确实依赖于默认安装路径(或您希望在其下搜索的任何硬编码路径)。

更改您的开发环境要求

您可以做的最后一件事是要求开发人员使用(或以某种方式调用)vsdevcmd.bat 来使用 VS 开发环境。这将使他们的 MSBuild 以及 VS 环境中的任何其他工具进入他们的 %PATH%。这确实对您的开发团队提出了要求,但始终是官方支持的查找 msbuild.exe.

的方法

如果您安装了 .NET Core 工具预览版 3 或更高版本,dotnet CLI 应该默认在 %PATH% 上可用(即使您没有构建 .NET Core项目),所以你可以试试 dotnet msbuild。参考 https://github.com/dotnet/docs/blob/master/docs/core/preview3/tools/dotnet-msbuild.md

Microsoft 已经创建了一个工具来查找 Visual Studio 2017 和更高版本 https://github.com/Microsoft/vswhere

的位置

this 博客 post 中描述了该选项和更新的选项。

既然 VS 2017 已经发布了,我认为添加我的 2 美分可能会有用:

正在创建批处理文件:

打开记事本

复制以下内容并粘贴到记事本中,将您要构建的解决方案替换为[此处为我的解决方案名称]:

@echo off

:variables
SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio17\Community\MSBuild.0\Bin\msbuild.exe"
SET solutionDirectory=[My Solution Location Here]
SET batchFileLocation=[BatchFileLocation Here]

cd %solutionDirectory%

echo Building MS files for [My Solution Name Here].

call %msBuildLocation% [My Solution Name].sln /p:Configuration=Debug /m:4 /v:M /fl /flp:LogFile=msbuild.log;Verbosity=Normal /nr:false  /consoleloggerparameters:Summary;ShowTimestamp;ShowEventId;PerformanceSummary
echo -
echo --------Done building [My solution name here].--------------
echo -

cd %batchFileLocation%

使用 .bat 扩展名将批处理文件另存为任何内容。确保 select 所有文件而不是 .txt 否则它将无法工作。 通过在保存文件的位置发出 cd 命令来调用批处理文件,它应该可以工作。或者,只需双击。完成。

请注意,我的 visual studio 版本是社区;您需要用适当的版本替换路径。

我还 运行 我的 CI 服务器上的 bat 文件中的构建工具:我找到的新位置是:

%programfiles(x86)%\Microsoft Visual Studio17\BuildTools\MSBuild.0\Bin\msbuild.exe

最简单的方法...

  • 盈利;构建工具将安装到一个单独的位置,这是你安装它的任何地方的标准,无论你的 VS SKU(专业/企业/社区都安装到不同的路径)
  • 新位置C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\MSBuild.0\Bin\msbuild.exe

发布这篇文章是为了那些仍然试图在机器上找到最新版本的 msbuild 并回退到旧版本(如果可用)的人。我发现这个 powershell 片段可以解决问题,它很容易成为 invoked from a bat file.

Function Find-MsBuild([int] $MaxVersion = 2017)
{
    $agentPath = "$Env:programfiles (x86)\Microsoft Visual Studio17\BuildTools\MSBuild.0\Bin\msbuild.exe"
    $devPath = "$Env:programfiles (x86)\Microsoft Visual Studio17\Enterprise\MSBuild.0\Bin\msbuild.exe"
    $proPath = "$Env:programfiles (x86)\Microsoft Visual Studio17\Professional\MSBuild.0\Bin\msbuild.exe"
    $communityPath = "$Env:programfiles (x86)\Microsoft Visual Studio17\Community\MSBuild.0\Bin\msbuild.exe"
    $fallback2015Path = "${Env:ProgramFiles(x86)}\MSBuild.0\Bin\MSBuild.exe"
    $fallback2013Path = "${Env:ProgramFiles(x86)}\MSBuild.0\Bin\MSBuild.exe"
    $fallbackPath = "C:\Windows\Microsoft.NET\Framework\v4.0.30319"

    If ((2017 -le $MaxVersion) -And (Test-Path $agentPath)) { return $agentPath } 
    If ((2017 -le $MaxVersion) -And (Test-Path $devPath)) { return $devPath } 
    If ((2017 -le $MaxVersion) -And (Test-Path $proPath)) { return $proPath } 
    If ((2017 -le $MaxVersion) -And (Test-Path $communityPath)) { return $communityPath } 
    If ((2015 -le $MaxVersion) -And (Test-Path $fallback2015Path)) { return $fallback2015Path } 
    If ((2013 -le $MaxVersion) -And (Test-Path $fallback2013Path)) { return $fallback2013Path } 
    If (Test-Path $fallbackPath) { return $fallbackPath } 

    throw "Yikes - Unable to find msbuild"
}


$msbuildPath = Find-MsBuild 2017

所以我有 Community Edition 2017,对我来说路径是: C:\Program Files (x86)\Microsoft Visual Studio17\Community\MSBuild.0\Bin\

此线程上的其他解决方案向我抛出异常。

我维护了一个非常简单的 PowerShell 脚本 (gist) 运行 CI/CLI 使用正确配置的 Visual Studio 环境变量构建。它使用 vswhere.exeVsDevCmd.bat。作为 Azure DevOps 管道的一部分,它在构建代理上运行良好。特别是对于 C++ 项目,正确设置 INCLUDELIB 至关重要,这就是 VsDevCmd.bat 所做的。

例如,运行 使用 MSBuild 构建当前文件夹中的解决方案:

powershell -f _invoke-build.ps1 -buildCommand "msbuild ."

将 VS' INCLUDE 环境变量复制到剪贴板(为了好玩):

powershell -f _invoke-build.ps1 -buildCommand "set INCLUDE | clip"

脚本的当前版本:

<#
  .Synopsis
    Find Visual Studio and run its VsDevCmd.bat, then run a build command.

  .Example
    powershell -f _invoke-build.ps1 -buildCommand "msbuild ."

  .Link
    https://gist.github.com/noseratio/843bb4d9c410c42081fac9d8b7a33b5e
#>

#Requires -Version 5.0
# by @noseratio

param([Parameter(Mandatory = $true)] [string] $buildCommand)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

echo "Building via '$buildCommand' ..."

$vs_not_found = "Visual Studio hasn't been detected!"

$vswhere = "${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe"
if (!(Test-Path $vswhere)) { throw $vs_not_found }

$vs_ide_path = $(& $vswhere -format value -property productPath)
if (!(Test-Path $vs_ide_path)) { throw $vs_not_found }

$vs_ide_folder = "$(Split-Path $vs_ide_path)"
$vs_dev_cmd = "$vs_ide_folder/../Tools/VsDevCmd.bat"
$invoke = "call ""$vs_dev_cmd"" && cd ""$pwd"" && $buildCommand"

# we need to run via CMD for proper propagation of Visual Studio environment vars
& $env:comspec /s /c ""$invoke""
if (!$?) { throw "Failed with error code: $LastExitCode" }