最近我将项目格式进行了升级,从旧的 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. static、final和finalize详解

    一.static 修饰符 数据共享 成员变量(实例变量)和静态变量(类变量)的区别 两个变量的生命周期不同 成员变量随对象的创建而存在,随对象被回收而释放 静态变量随类的加载而存在,随类的消失而消失 ...

  2. HttpGet/HttpPost请求方法

    /// <summary> /// HttpGet请求 /// </summary> /// <param name="url">HttpGet ...

  3. 调试bug的几种方法

    1.php中的dump,echo,exit 2.浏览器的f12 3.安装xdebug扩展(debugger调试器,profiler探查器,trace代码跟踪) profile日志能记录函数的执行耗时和 ...

  4. angular中的cookies与cookieStore区别

    设置cookie用put()方法: $cookies.put(key, value[, options]); $cookieStore.put(key, value); 例如设置一个cookie,名为 ...

  5. 【Python】常用排序算法的python实现和性能分析

    作者:waterxi 原文链接 背景 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整 ...

  6. [Mybatis]Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析

    转自:https://www.cnblogs.com/fangjian0423/p/spring-mybatis-MapperScannerConfigurer-analysis.html Mappe ...

  7. DOM: EVENT FLOW

    捕获阶段(capture phase) 捕获阶段的定义如下(w3c):The event object propagate through the target's ancestors from th ...

  8. 转:Hive SQL的编译过程

    Hive是基于Hadoop的一个数据仓库系统,在各大公司都有广泛的应用.美团数据仓库也是基于Hive搭建,每天执行近万次的Hive ETL计算流程,负责每天数百GB的数据存储和分析.Hive的稳定性和 ...

  9. C++:获取指定目录下的所有文件

    1.获得指定目录下的所有文件(不搜索子文件夹) 需要包含的头文件 #include <io.h> #include <string> #include <vector&g ...

  10. 【51nod-1289】大鱼吃小鱼(思维)

    这道题我想的方法是用栈,每次去出栈顶两元素,比较是否相对,相对的话合并后压入栈.类似括号匹配. #include <bits/stdc++.h> using namespace std; ...