我如何在我的程序运行的机器上编写代码以获取MSBuild路径?
我可以从环境中获取 .NET 版本,但是否有一种方法可以获取特定 .NET 版本的正确文件夹路径?
查看注册表,看起来像是
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\2.0
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\3.5
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0
也许这正是您想要的;打开 regedit.exe 并查看。
reg.exe query "HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0" /v MSBuildToolsPath
dir HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\
您还可以将 MSBuild.exe 的路径打印到命令行:
reg.exe query "HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0" /v MSBuildToolsPath
cmd
(或其他您正在运行的进程)上使用/reg:32
或/reg:64
来明确获取该路径。 - Simon BuchanComputer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\MSBuild\ToolsVersions\4.0\MSBuildToolsPath
下。 - Sen Jacob&"${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe
&"${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.PackageGroup.TestTools.Core -find Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.PackageGroup.TestTools.Core -find Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe
(请注意,上述说明已经稍作修改,以适应您的使用情况。特别是,我包括了 -prerelease
标志以允许选择预览版和 RC 版本安装,并且 -products *
用于检测 Visual Studio Build Tools 安装。根据您的需要进行配置。)
经过两年多的等待,终于在2019年,微软倾听了我们的心声,并提供了一种查找这些重要可执行文件的方法!如果您已安装Visual Studio 2017或更新版本,则可以查询vswhere
实用程序以获取MSBuild等的位置。由于vswhere
保证位于%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe
,因此不再需要引导、路径硬编码和注册表探测。
魔法在于-find
参数, 添加于版本2.6.2。您可以通过运行vswhere
或检查其文件属性来确定安装的版本。如果您有旧版本,您可以简单地下载最新版本并覆盖现有的%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe
。
vswhere.exe
是一个独立的可执行文件,因此您可以从任何有互联网连接的地方下载和运行它。这意味着您的构建脚本可以检查它们运行的环境是否正确设置,作为其中一种选择。
如果您已安装Chocolatey,您也可以使用相关的vswhere
软件包。
msbuild
(特别是在使用Visual Studio命令行时),就会使用该文件。要查看在命令行上键入msbuild
时使用的是哪个文件,请执行以下操作:输入where msbuild
。如果报告的内容与VSWHERE所说的最新和最好的版本不同,则必须指定要使用的msbuild.exe
的完整路径或调整PATH变量以适应需求。 - Jinlye如果要使用MSBuild用于.Net 4,则可以使用以下PowerShell命令获取可执行文件的路径。如果您想要版本2.0或3.5,则只需更改$dotNetVersion变量。
要运行可执行文件,您需要在$msbuild变量前加上&。这将执行该变量。
# valid versions are [2.0, 3.5, 4.0]
$dotNetVersion = "4.0"
$regKey = "HKLM:\software\Microsoft\MSBuild\ToolsVersions\$dotNetVersion"
$regProperty = "MSBuildToolsPath"
$msbuildExe = join-path -path (Get-ItemProperty $regKey).$regProperty -childpath "msbuild.exe"
&$msbuildExe
$dotNetVersion
12.0 (vs 2013) 和 14.0 (vs 2015)(如果已安装)的工作。 - JulianHKLM:\software\Microsoft\MSBuild\ToolsVersions
键下不添加任何值。相反,您需要从 HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7\15.0
获取VS2017安装目录,然后附加 MSBuild\15.0\Bin\MSBuild.exe
以获取MSBuild EXE位置。 - Ian Kemp在Windows 7中进行cmd shell脚本编写时,我在批处理文件中使用以下片段来查找.NET Framework版本4中的MSBuild.exe。我假设版本4存在,但不假定子版本。这不是完全通用的,但对于快速脚本可能有帮助:
set msbuild.exe=
for /D %%D in (%SYSTEMROOT%\Microsoft.NET\Framework\v4*) do set msbuild.exe=%%D\MSBuild.exe
根据我的使用情况,如果这样做没有起作用,我会以错误的方式退出批处理文件:
if not defined msbuild.exe echo error: can't find MSBuild.exe & goto :eof
if not exist "%msbuild.exe%" echo error: %msbuild.exe%: not found & goto :eof
您可以使用此试用版PowerShell命令从注册表中获取MSBuildToolsPath
。
Resolve-Path HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\* |
Get-ItemProperty -Name MSBuildToolsPath
MSBuildToolsPath : C:\Program Files (x86)\MSBuild\12.0\bin\amd64\
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions
PSChildName : 12.0
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
MSBuildToolsPath : C:\Program Files (x86)\MSBuild\14.0\bin\amd64\
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions
PSChildName : 14.0
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
MSBuildToolsPath : C:\Windows\Microsoft.NET\Framework64\v2.0.50727\
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\2.0
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions
PSChildName : 2.0
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
MSBuildToolsPath : C:\Windows\Microsoft.NET\Framework64\v3.5\
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\3.5
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions
PSChildName : 3.5
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
MSBuildToolsPath : C:\Windows\Microsoft.NET\Framework64\v4.0.30319\
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions
PSChildName : 4.0
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
或从文件系统中获取
Resolve-Path "C:\Program Files (x86)\MSBuild\*\Bin\amd64\MSBuild.exe"
Resolve-Path "C:\Program Files (x86)\MSBuild\*\Bin\MSBuild.exe"
Path
----
C:\Program Files (x86)\MSBuild\12.0\Bin\amd64\MSBuild.exe
C:\Program Files (x86)\MSBuild\14.0\Bin\amd64\MSBuild.exe
C:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe
C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe
Resolve-Path 'C:\Program Files*\Microsoft Visual Studio\*\Professional\Msbuild\Current\bin\MSBuild.exe'
- Sir CodesALot@AllenSanborn有一个很棒的PowerShell版本,但有些人需要使用批处理脚本来进行构建。
这是@bono8106回答的应用版本。
msbuildpath.bat
@echo off
reg.exe query "HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" /v MSBuildToolsPath > nul 2>&1
if ERRORLEVEL 1 goto MissingMSBuildRegistry
for /f "skip=2 tokens=2,*" %%A in ('reg.exe query "HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" /v MSBuildToolsPath') do SET "MSBUILDDIR=%%B"
IF NOT EXIST "%MSBUILDDIR%" goto MissingMSBuildToolsPath
IF NOT EXIST "%MSBUILDDIR%msbuild.exe" goto MissingMSBuildExe
exit /b 0
goto:eof
::ERRORS
::---------------------
:MissingMSBuildRegistry
echo Cannot obtain path to MSBuild tools from registry
goto:eof
:MissingMSBuildToolsPath
echo The MSBuild tools path from the registry '%MSBUILDDIR%' does not exist
goto:eof
:MissingMSBuildExe
echo The MSBuild executable could not be found at '%MSBUILDDIR%'
goto:eof
build.bat
@echo off
call msbuildpath.bat
"%MSBUILDDIR%msbuild.exe" foo.csproj /p:Configuration=Release
对于Visual Studio 2017 / MSBuild 15,Aziz Atif(撰写Elmah的人)编写了一批处理脚本。
build.cmd Release Foo.csproj
https://github.com/linqpadless/LinqPadless/blob/master/build.cmd
@echo off
setlocal
if "%PROCESSOR_ARCHITECTURE%"=="x86" set PROGRAMS=%ProgramFiles%
if defined ProgramFiles(x86) set PROGRAMS=%ProgramFiles(x86)%
for %%e in (Community Professional Enterprise) do (
if exist "%PROGRAMS%\Microsoft Visual Studio\2017\%%e\MSBuild\15.0\Bin\MSBuild.exe" (
set "MSBUILD=%PROGRAMS%\Microsoft Visual Studio\2017\%%e\MSBuild\15.0\Bin\MSBuild.exe"
)
)
if exist "%MSBUILD%" goto :restore
set MSBUILD=
for %%i in (MSBuild.exe) do set MSBUILD=%%~dpnx$PATH:i
if not defined MSBUILD goto :nomsbuild
set MSBUILD_VERSION_MAJOR=
set MSBUILD_VERSION_MINOR=
for /f "delims=. tokens=1,2,3,4" %%m in ('msbuild /version /nologo') do (
set MSBUILD_VERSION_MAJOR=%%m
set MSBUILD_VERSION_MINOR=%%n
)
if not defined MSBUILD_VERSION_MAJOR goto :nomsbuild
if not defined MSBUILD_VERSION_MINOR goto :nomsbuild
if %MSBUILD_VERSION_MAJOR% lss 15 goto :nomsbuild
if %MSBUILD_VERSION_MINOR% lss 1 goto :nomsbuild
:restore
for %%i in (NuGet.exe) do set nuget=%%~dpnx$PATH:i
if "%nuget%"=="" (
echo WARNING! NuGet executable not found in PATH so build may fail!
echo For more on NuGet, see https://github.com/nuget/home
)
pushd "%~dp0"
nuget restore ^
&& call :build Debug %* ^
&& call :build Release %*
popd
goto :EOF
:build
setlocal
"%MSBUILD%" /p:Configuration=%1 /v:m %2 %3 %4 %5 %6 %7 %8 %9
goto :EOF
:nomsbuild
echo Microsoft Build version 15.1 (or later) does not appear to be
echo installed on this machine, which is required to build the solution.
exit /b 1
function Get-MSBuild-Path {
$vs14key = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0"
$vs15key = "HKLM:\SOFTWARE\wow6432node\Microsoft\VisualStudio\SxS\VS7"
$msbuildPath = ""
if (Test-Path $vs14key) {
$key = Get-ItemProperty $vs14key
$subkey = $key.MSBuildToolsPath
if ($subkey) {
$msbuildPath = Join-Path $subkey "msbuild.exe"
}
}
if (Test-Path $vs15key) {
$key = Get-ItemProperty $vs15key
$subkey = $key."15.0"
if ($subkey) {
$msbuildPath = Join-Path $subkey "MSBuild\15.0\bin\amd64\msbuild.exe"
}
}
return $msbuildPath
}
基于@dh_cgn's answer的一行代码:
(Resolve-Path ([io.path]::combine(${env:ProgramFiles(x86)}, 'Microsoft Visual Studio', '*', '*', 'MSBuild', '*' , 'bin' , 'msbuild.exe'))).Path
它选择所有现有的路径,例如:C:\Program Files (x86)\Microsoft Visual Studio\*\*\MSBuild\*\bin\msbuild.exe
。
通配符星号是:
请注意,此命令会选择按字母顺序排列的第一个与表达式匹配的路径。为了缩小范围,请将通配符替换为特定元素,例如年份或工具版本。
amd64
添加到查找 64 位的路径中:(Resolve-Path ([io.path]::combine(${env:ProgramFiles(x86)}, 'Microsoft Visual Studio', '*', '*', 'MSBuild', '*' , 'bin' , 'amd64', 'msbuild.exe'))).Path
- Ray DepewHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\2.0
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\3.5
请提供可执行文件的位置。
但如果您需要保存任务扩展的位置,则在以下位置:
%ProgramFiles%\MSBuild
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\amd64\
。 - nZeus