当前位置: 首页 > news >正文

为 NuGet 指定检测的 MSBuild 路径或版本,解决 MSBuild auto-detection: using msbuild version 自动查找路径不合适的问题

使用 nuget restore 命令还原项目的 NuGet 包的时候,NuGet 会尝试自动检测计算机上已经安装的 MSBuild。不过,如果你同时安装了 Visual Studio 2017 和 Visual Studio 2019,那么 NuGet 有可能找到错误版本的 MSBuild。

本文介绍如何解决自动查找版本错误的问题。


本文内容

    • 问题
    • 使用命令行参数解决
    • 修改环境变量解决

问题

当我们敲下 nuget restore 命令的时候,命令行的第 2 行会输出自动检测到的 MSBuild 版本号,就像下面的输出一样:

NuGet Version: 5.0.2.5988
MSBuild auto-detection: using msbuild version ‘15.9.21.664’ from ‘C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin’. Use option -MSBuildVersion to force nuget to use a specific version of MSBuild.

实际上我计算机上同时安装了 Visual Studio 2017 和 Visual Studio 2019,我有两个不同版本的 MSBuild:

  • 15.9.21.664
    • C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
  • 16.1.76.45076
    • C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin

要让 NuGet 找到正确版本的 MSBuild.exe,我们有三种方法。

使用命令行参数解决

实际上前面 nuget restore 命令的输出中就已经可以看出来其中一个解决方法了,即使用 -MSBuildVersion 来指定 MSBuild 的版本号。

虽然命令行输出中推荐使用了 -MSBuildVersion 选项来指定 MSBuild 的版本,但是实际上实现同样功能的有两个不同的选项:

  • -MSBuildPath 自 NuGet 4.0 开始新增的选项,指定 MSBuild 程序的路径。
  • -MSBuildVersion

当同时指定上面两个选项时,-MSBuildPath 选项优先级高于 -MSBuildVersion 选项。

于是我们的 nuget restore 命令改成这样写:

> nuget restore -MSBuildPath "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin"

输出现在会使用期望的 MSBuild 了:

Using Msbuild from 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin'.

修改环境变量解决

NuGet 的命令行自动查找 MSBuild.exe 时,是通过环境变量中的 PATH 变量来找的。会找到 PATH 中第一个包含 msbuild.exe 文件的路径,将其作为自动查找到的 MSBuild 的路径。

所以,我们的解决方法是,如果找错了,我们就把期望正确的 MSBuild 所在的路径设置到不期望的 MSBuild 路径的前面。就像下图这样,我们把 2019 版本的 MSBuild 设置到了 2017 版本的前面。

设置环境变量

以下是 NuGet 项目中自动查找 MSBuild.exe 文件的方法,源代码来自 https://github.com/NuGet/NuGet.Client/blob/2b45154b8568d6cbf1469f414938f0e3e88e3704/src/NuGet.Clients/NuGet.CommandLine/MsBuildUtility.cs#L986。

private static string GetMSBuild()
{
    var exeNames = new [] { "msbuild.exe" };

    if (RuntimeEnvironmentHelper.IsMono)
    {
        exeNames = new[] { "msbuild", "xbuild" };
    }

    // Try to find msbuild or xbuild in $Path.
    var pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(new[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);

    if (pathDirs?.Length > 0)
    {
        foreach (var exeName in exeNames)
        {
            var exePath = pathDirs.Select(dir => Path.Combine(dir, exeName)).FirstOrDefault(File.Exists);
            if (exePath != null)
            {
                return exePath;
            }
        }
    }

    return null;
}

我故意在桌面上放了一个老旧的 MSBuild.exe,然后将此路径设置到环境变量 PATH 的前面,出现了编译错误。

编译失败


参考资料

  • NuGet CLI restore command - Microsoft Docs
  • How Can I Tell NuGet What MSBuild Executable to Use? - Stack Overflow
  • VS2017 MSBuild autodetection takes MSBuild/v14 instead of v15 for WPF project - Stack Overflow

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 解决方案文件 sln 中的项目类型 GUID
  • 两种方法设置 .NET/C# 项目的编译顺序,而不影响项目之间的引用
  • 理解 Visual Studio 解决方案文件格式(.sln)
  • nuget.exe 还原解决方案 NuGet 包的时候出现错误:调用的目标发生了异常。Error parsing the nested project section in solution file
  • 找出 .NET Core SDK 是否使用预览版的全局配置文件在哪里(探索篇)
  • 如何在 Visual Studio 2019 中设置使用 .NET Core SDK 的预览版(全局生效)
  • 使用基于 Roslyn 的 Microsoft.CodeAnalysis.PublicApiAnalyzers 来追踪项目的 API 改动,帮助保持库的 API 兼容性
  • Visual Studio 2019 中使用 .NET Core 预览版 SDK 的全局配置文件在哪里?
  • 推荐几款连字字体,在代码编辑器中启用连字字体(Visual Studio Code)
  • 找回你 C 盘丢失的空间(SpaceSniffer)
  • System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
  • 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息
  • 如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全
  • 通过 mklink 收集本地文件系统的所有 NuGet 包输出目录来快速调试公共组件代码
  • 设计一个 .NET 可用的弱引用集合(可用来做缓存池使用)
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 【347天】每日项目总结系列085(2018.01.18)
  • Hexo+码云+git快速搭建免费的静态Blog
  • JavaScript设计模式系列一:工厂模式
  • Java基本数据类型之Number
  • JSONP原理
  • python 装饰器(一)
  • spring boot下thymeleaf全局静态变量配置
  • Vim Clutch | 面向脚踏板编程……
  • 从零搭建Koa2 Server
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 订阅Forge Viewer所有的事件
  • 前嗅ForeSpider采集配置界面介绍
  • 使用 QuickBI 搭建酷炫可视化分析
  • 手写一个CommonJS打包工具(一)
  • 数据科学 第 3 章 11 字符串处理
  • 项目管理碎碎念系列之一:干系人管理
  • 写给高年级小学生看的《Bash 指南》
  • 硬币翻转问题,区间操作
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 阿里云服务器购买完整流程
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (003)SlickEdit Unity的补全
  • (10)ATF MMU转换表
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (差分)胡桃爱原石
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (九十四)函数和二维数组
  • (转)EXC_BREAKPOINT僵尸错误
  • .htaccess配置常用技巧
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .Net - 类的介绍
  • .Net Remoting(分离服务程序实现) - Part.3
  • .net wcf memory gates checking failed
  • .NET分布式缓存Memcached从入门到实战