最近我将项目格式进行了升级,从旧的 csproj 升级成了新的 csproj;NuGet 包管理的方式也从 packages.config 升级成了 PackageReference。然而迁移完才发现,这个项目竟然还依赖了大量的从 NuGet 2.x 时代发布的 NuGet 包,这些包并不能在 PackageReference 下好好工作。

于是,我准备将所有这些包都进行升级。本文将介绍最简单的升级步骤。


 

回顾遇到的问题

如果你之前迁移过 csproj 文件,可能会遇到问题。关于迁移 csproj 文件,可以阅读:将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - 吕毅

如果你并没有迁移过 csproj 文件,只是升级了 NuGet 的包管理方式,也可能会遇到问题。关于自动迁移 NuGet 包管理方式,可以阅读:自动将 NuGet 包的引用方式从 packages.config 升级为 PackageReference - 吕毅

在自动迁移那篇文章中,我提到了一些兼容性问题,最大的莫过于 Install.ps1 脚本不再执行:

使用 PackageReference 后,在安装和写在的过程中 install.ps1 脚本将不再执行。如果有一些行为依赖于此脚本,那么这个 NuGet 包的行为可能不正常。

但是,不用担心!install.ps1 的存在是因为 packages.config 不支持 PackageReference 中的一些新特性(例如 NuGet 包中新的目录结构,例如包中自带的 msbuild targets)。所以,如果 NuGet 包在发布时满足目录要求,那么即便 install.ps1 不用执行也能保证包的行为正常。

虽然我提到不用担心,但其实旧的一些包里并没有准备 build 文件夹,也没有准备 props 或者 targets 文件。所以一小部分特别依赖于 install.ps1 的 NuGet 包是没有办法在新格式中生效的。

最简升级步骤

知道了问题所在,那么我们的根本便是将 Install.ps1 升级成新的 props 或者 targets。

如果你不清楚 props 或者 targets 是什么意思,或者不知道怎么写它们,可以阅读我的另一篇文章理解 C# 项目 csproj 文件格式的本质和编译流程 - 吕毅

第一步:将 install.ps1 翻译成 targets

最简单的方法,直接去安装好 NuGet 的项目的 csproj 文件中去看究竟生成了那些代码。一般来说,这些 install.ps1 中多是生成 Target 节点。

而我们要做的,就是新建一个 build 文件夹,在其中新建 PackageId.targets 文件,以便将生成的 Target 节点中的内容复制过去。前面那一句的 PackageId 指的是这个 NuGet 包的包 Id。比如,在我的例子中,是 Walterlv.NuGetDemo.targets。

比如,生成的 Target 节点是这样的:

<!-- 项目 csproj 文件 -->
<Target Name="WalterlvNuGetDemo" BeforeTargets="AfterCompile">
<ItemGroup>
<BinCopyItems Include="..\..\packages\Walterlv.NuGetDemo.1.2.3.0\tools\bin\*.*" />
<x64CopyItems Include="..\..\packages\Walterlv.NuGetDemo.1.2.3.0\tools\bin_x64\*.*" />
<x86CopyItems Include="..\..\packages\Walterlv.NuGetDemo.1.2.3.0\tools\bin_x86\*.*" />
</ItemGroup>
<Copy SourceFiles="@(BinCopyItems)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="True" />
<Copy SourceFiles="@(x86CopyItems)" DestinationFolder="$(OutputPath)x86" SkipUnchangedFiles="True" />
<Copy SourceFiles="@(x64CopyItems)" DestinationFolder="$(OutputPath)x64" SkipUnchangedFiles="True" />
</Target>

那么,直接将这些文件复制到 PackageId.targets 文件中:

<!-- Walterlv.NuGetDemo.targets 文件 -->
<Project>
<Target Name="WalterlvNuGetDemo" BeforeTargets="AfterCompile">
<ItemGroup>
<BinCopyItems Include="..\..\packages\Walterlv.NuGetDemo.1.2.3.0\tools\bin\*.*" />
<x64CopyItems Include="..\..\packages\Walterlv.NuGetDemo.1.2.3.0\tools\bin_x64\*.*" />
<x86CopyItems Include="..\..\packages\Walterlv.NuGetDemo.1.2.3.0\tools\bin_x86\*.*" />
</ItemGroup>
<Copy SourceFiles="@(BinCopyItems)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="True" />
<Copy SourceFiles="@(x86CopyItems)" DestinationFolder="$(OutputPath)x86" SkipUnchangedFiles="True" />
<Copy SourceFiles="@(x64CopyItems)" DestinationFolder="$(OutputPath)x64" SkipUnchangedFiles="True" />
</Target>
</Project>

然后,修改其中的路径,将相对于安装项目路径的地方更换成相对于此 targets 文件的路径:

<!-- Walterlv.NuGetDemo.targets 文件 -->
<Project>
<Target Name="WalterlvNuGetDemo" BeforeTargets="AfterCompile">
<ItemGroup>
<BinCopyItems Include="$(MSBuildThisFileDirectory)..\tools\bin\*.*" />
<x64CopyItems Include="$(MSBuildThisFileDirectory)..\tools\bin_x64\*.*" />
<x86CopyItems Include="$(MSBuildThisFileDirectory)..\tools\bin_x86\*.*" />
</ItemGroup>
<Copy SourceFiles="@(BinCopyItems)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="True" />
<Copy SourceFiles="@(x86CopyItems)" DestinationFolder="$(OutputPath)x86" SkipUnchangedFiles="True" />
<Copy SourceFiles="@(x64CopyItems)" DestinationFolder="$(OutputPath)x64" SkipUnchangedFiles="True" />
</Target>
</Project>

第二步:修改 nuspec 文件,加入 targets

接着,去 nuspec 文件中,删除 Install.ps1 和 Uninstall.ps1,然后新增我们刚刚写的 targets 文件。

<files>
<!-- 省略其他一些文件 -->
<file src="tools\bin\DemoNativeLib.dll" target="tools\bin"/>
<!-- 删除 <file src="tools\Install.ps1" target="tools"/> -->
<!-- 删除 <file src="tools\Uninstall.ps1" target="tools"/> -->
<!-- 省略其他一些文件 -->
<file src="build\Walterlv.NuGetDemo.targets" target="build"/>
</files>

重新打包和测试 NuGet 包

以上改完了之后,基本上就迁移完了。

这样的改动是最小的,既能够保证旧的 packages.config 能够顺利迁移,也能保证新的 PackageReference 行为保持不变。

如何最快速地将旧的 NuGet 包 (2.x, packages.config) 升级成新的 NuGet 包 (4.x, PackageReference)的更多相关文章

  1. 自动将 NuGet 包的引用方式从 packages.config 升级为 PackageReference

    在前段时间我写了一篇迁移 csproj 格式的博客 将 WPF.UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件,不过全过程是手工进行的,而且到最后处理 XAM ...

  2. 在VS中自动生成NuGet包以及搭建自己的或单位内部的NuGet服务器

    关于NuGet的介绍已经很多,可以参考下面的: NuGet学习笔记(1)--初识NuGet及快速安装使用 http://kb.cnblogs.com/page/143190/ NuGet学习笔记(2) ...

  3. 将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件

    写过 .NET Standard 类库或者 .NET Core 程序的你一定非常喜欢微软为他们新开发的项目文件(对于 C#,则是 csproj 文件).这种文件非常简洁,组织一个庞大的项目也只需要聊聊 ...

  4. 项目 XXX 的 NuGet 程序包还原失败:找不到“xxx”版本的程序包“xxx”

    项目 XXX 的 NuGet 程序包还原失败:找不到“xxx”版本的程序包“xxx” 编译新下载的代码出错 修改包管理器的源为 http://www.nuget.org/api/v2/ .重试后成功 ...

  5. Error This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. T

    错误提示: Severity Code Description Project File Line Suppression StateError This project references NuG ...

  6. Vs 中关于项目中的某 NuGet 程序包还原失败:找不到“xxx”版本的程序包“xxx”

    问题:     首先出现这个bug的是在我的vs2017社区版的ide上,这两天使用了出现了一个非常神奇的问题,就是我程序中的nuget包总提示找不到源文件,并且我点击Nuget还原的话还一直提示着一 ...

  7. NuGet Packages are missing,This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.

    错误内容 This project references NuGet package(s) that are missing on this computer. Use NuGet Package R ...

  8. 解决“程序包管理器控制台”输入命令找不到Nuget包问题

    问题: 问题原因: Nuget源的地址上不去 解决办法: 1.将Nuget源更新为可以国内使用的官方Nuget源. 1)打开VS2013:工具-->Nuget程序包管理器-->程序包管理器 ...

  9. 手动更新了packages.config Nuget配置文件,自动引用dll

    通过Google查询到:http://stackoverflow.com/questions/6876732/how-do-i-get-nuget-to-install-update-all-the- ...

随机推荐

  1. Grunt Part 2

    Objectives and Outcomes In this exercise, you will continue to learn to use Grunt, the task runner. ...

  2. codeforces570D Tree Requests

    题目链接:codeforces570D 正解:$dsu$ $on$ $tree$ 解题报告: 考虑这又是一类子树内的不带修改统计问题,直接上$dsu$ $on$ $tree$好咯. 直接按上一道题的做 ...

  3. DNS和Bind配置指南

    /////////////////////////////目录//////////////////////////////////////一.DNS原理相关二.使用bind搭建最简单的DNS服务器三. ...

  4. 尽量不要使用using namespace std

    C++标准程序库中的所有标识符都被定义于一个名为std的namespace中. namespace是指标识符的各种可见范围.命名空间用关键字namespace 来定义.命名空间是C++的一种机制,用来 ...

  5. mysql数据库优化课程---17、mysql索引优化

    mysql数据库优化课程---17.mysql索引优化 一.总结 一句话总结:一些字段可能会使索引失效,比如like,or等 1.check表监测的使用场景是什么? 视图 视图建立在两个表上, 删除了 ...

  6. pfSense 2.4.3 发布,包含重要的安全修复补丁

    pfSense 2.4.3 已发布,本次更新包含重要的安全修复和 bug 修复,还引入了一些新特性,具体如下. 值得关注的更新 包含一些重要的安全修复补丁: Kernel PTI mitigation ...

  7. Struts2异常处理配置

    <package name="lee" extends="struts-default"> <!--定义全局结构映射 --> <g ...

  8. OpenStack Mitaka Neutron SR-IOV配置

    ### 一.在所有节点(控制节点.计算节点) 1.修改BIOS ``` BOIS里面开启SR-IOV功能 开启 VT-d (inter virtualization technology)和 SR-I ...

  9. ActiveMQ教程(消息发送和接受)

    一 环境的搭建 version为你的版本号 如果你是普通的项目的话,创建一个lib文件夹,导入相应的jar包到你的lib中,jar包为:activemq-all-{version}.jar.log4j ...

  10. 轮播图插件 SuperSlide2.1滑动门jQuery插件

    http://down.admin5.com/demo/code_pop/18/562/ SuperSlide2.1滑动门jQuery插件