Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >无需安装 VS2019,在 Visual Studio 2022 中编译 .NET Framework 4.5/4/3.5 这样的古老框架

无需安装 VS2019,在 Visual Studio 2022 中编译 .NET Framework 4.5/4/3.5 这样的古老框架

作者头像
walterlv
发布于 2023-10-23 03:13:20
发布于 2023-10-23 03:13:20
2.1K0
举报

Visual Studio 2022 已正式发布!着急升级的小伙伴兴致勃勃地升级并卸载了原来的 Visual Studio 2019 后,发现自己的几个库项目竟然无法编译通过了。究其原因,是因为我的一些库依旧在支持古老的 .NET Framework 4.5 框架,而 Visual Studio 2022 不再附带如此古老的目标包了。

我之前在 另一篇文章 中告诉大家通过将 Visual Studio 2019 装回来的方式解决这个问题,但是有小伙伴不想安装 Visual Studio 2019;所以本文用另外一种方法,无需安装 Visual Studio 2019,也无需单独安装 .NET Framework 目标包。


无法编译 .NET Framework 4.5 项目

为了更广泛的适用于各种项目,我的一些库兼容的框架版本是非常古老的(比如下图截取的这张)。可是卸载掉 Visual Studio 2019 只留下 Visual Studio 2022 之后这些项目就不再能编译通过了。如果点开 Visual Studio 2022 的安装程序,会发现已经删除掉了 .NET Framework 4.5 的目标包了,无法通过它安装回来。

关键步骤

第一步:安装 NuGet 包 Microsoft.NETFramework.ReferenceAssemblies

Microsoft.NETFramework.ReferenceAssemblies 这款 NuGet 包旨在解决没有目标包的时候编译 .NET Framework 框架的问题。因此,我们将通过安装此 NuGet 包来解决 Visual Studio 2022 中目标包的缺失问题。

正常你只需要在项目中安装这个 NuGet 包即可。如果你整个解决方案里所有项目都需要兼容 .NET Framwework 4.5 或者更加古老的 .NET 框架,也可以用 Directory.Build.props 文件,详见:使用 Directory.Build.props 管理多个项目配置 - 林德熙

1 2 3 4 5

<Project> <ItemGroup> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" /> </ItemGroup> </Project>

请特别注意

如果你正在开发的是库项目,那么在引用此 NuGet 包之后,应该加上 PrivateAssets="all" 来标记此 NuGet 包不会成为你自己的库的其中一个依赖。否则就会像下图一样有一个不期望的依赖。

▲ 不期望的依赖

▲ 正常的依赖

第二步:适配 Visual Studio 的特殊开发环境

如果你不用 VS2022,而只是使用 dotnet buildmsbuild 命令来编译,那么以上第一步完成后就够了。不过考虑到大家基本上都是用 Visual Studio 来开发,所以上述操作在 VS 中的水土不服也需要特别处理一下。

在项目的 csproj 文件中添加一个 Target:

1 2 3 4 5 6 7

<Target Name="WalterlvPackagesIncludeNetFrameworkReferences" BeforeTargets="GetReferenceAssemblyPaths" DependsOnTargets="Restore" Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' And '$(TargetFrameworkRootPath)' == '' "> <PropertyGroup> <TargetFrameworkRootPath Condition=" $(TargetFrameworkMoniker) == '.NETFramework,Version=v4.5' ">$(UserProfile).nuget\packages\microsoft.netframework.referenceassemblies.net45\1.0.2\build</TargetFrameworkRootPath> <TargetFrameworkRootPath Condition=" $(TargetFrameworkMoniker) == '.NETFramework,Version=v4.0' ">$(UserProfile).nuget\packages\microsoft.netframework.referenceassemblies.net40\1.0.2\build</TargetFrameworkRootPath> </PropertyGroup> </Target>

或者如果前面你是在 Directory.Build.props 文件中添加的引用,那么就在对应的 Directory.Build.targets 文件中添加这一段(没有此文件则新建)。

解释一下这段代码如何适配了 Visual Studio 的特殊开发环境:

  1. 猜测 VS 会缓存 TargetFrameworkRootPath 属性,一旦获取到其值将再也不会更新之,就算后面紧跟着还原 NuGet 包后值已被正常赋值了也不会使用(即使重启 VS 也是如此);于是我们在 TargetFrameworkRootPath 属性为 时手工给其赋上正确的值。
  2. 猜测 VS 在发现 TargetFrameworkRootPath 属性所对应的路径不存在时视为与空同等处理;所以我们 DependsOnTargets="Restore" 以便在第一次还原 NuGet 包相关路径还没有创建时马上完成 NuGet 包的还原以创建对应目录。

在使用了以上代码后,Visual Studio 2022 刚打开项目时会短暂提示缺少 .NET Framework 4.5 框架,但真正编译时此提示会消失。这些问题都是单独使用命令来编译时不会遇到的问题。我也尝试过其他的解决方法,但都不能完美消除此错误提示(如果你没有 WPF 项目的话,也可以通过创建名为 GetReferenceAssemblyPaths 的空 Target 跳过检查)。

写完上面的代码之后:

  1. 关闭 Visual Studio 2022
  2. 清理仓库,执行 git clean -xdf 命令(这会删除所有未被版本管理的文件,包括 Visual Studio 的各种缓存文件)
  3. 重新启动 Visual Studio 2022

一些注意事项

1. 需要覆盖整个解决方案中所有涉及到 .NET Framework 框架的项目

这个 NuGet 包的本质是在编译的时候设置 TargetFrameworkRootPath 属性到 NuGet 包里安装过来的目录,并且通过 <Reference Include="mscorlib" Pack="false" /> 指定额外引用 mscorelib,所以不会产生额外的引用。于是这种方式安装的 NuGet 包不像其他的 NuGet 包那样可以传递到其他引用它的项目。

你需要做的:

  1. 给所有含 .NET Framework 框架的项目安装 Microsoft.NETFramework.ReferenceAssemblies NuGet 包
  2. 如果不想直接给所有项目安装,可以使用 Directory.Build.props 来一并安装

2. 不支持同一个文件夹下有两个 csproj 项目的情况

有时候为了方便,当两个项目几乎所有文件都相同,只是项目配置不同时,我们会考虑将这两个项目放到同一个文件夹里面以共用文件。可惜这种方式组织的项目,跟本问所提供的方案不兼容。

如果解决方案中存在这样的项目组织方式,你会发现其他项目都能编译通过,唯独这两个项目依旧死在缺少 .NET Framework 45 目标包上。解决方法就是把这两个项目拆开成两个文件夹。

可是他们共用的文件怎么办?答案是在每个项目的 csproj 文件中添加下面几行:

1 2 3

<ItemGroup> <Compile Include="..\SomeCommonFolder\\*\*\\*.cs" Link="%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup>

即他们都去共同的目录下把文件都拉进来编译,并且以链接的方式显示到 Visual Studio 解决方案管理器里。详见:使用链接共享 Visual Studio 中的代码文件

另外,这里的 %(RecursiveDir) 是递归显示文件夹(否则所有文件会拍平到项目里),%(Filename) 是将链接显示成文件名,%(Extension) 是在文件名后面显示文件扩展名。经此写法,项目里显示的其他文件夹的文件看起来就像真的在这个项目里一样。

3. 对于经典 csproj 格式(而非 SDK 风格 csproj 格式)的情况

评论区 @afunc233回复 说经典 csproj 格式没办法使用本文所述的方法。

我个人建议还是迁移一下比较好,不难而且完全兼容旧格式的所有功能。迁移教程:将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成 Sdk 风格的 csproj

如果不想迁移,也可以试试官方的方法。但我不想尝试,所以就在线等 TA 在评论区的回复吧!

4. 不想折腾之一:还是装回 VS2019 吧

有时候,你可能会遇到各种意料之外的问题,超出我上面列举的坑。不想折腾的话,那就把 .NET Framework 4.5 目标包装回来吧,可参见:Visual Studio 2022 升级不再附带 .NET Framework 4.5 这种古老的目标包了,本文帮你装回来

5. 不想折腾之二:打死也不装回 VS2019

有时候,你可能会遇到各种意料之外的问题,超出我上面列举的坑。如果你跟我一样,无论如何都不想装回 VS2019,那么还有解决方法:直接把 .NET Framework 的引用全拷到项目里来。操作如下:

  1. Microsoft.NETFramework.ReferenceAssemblies NuGet 包的下载页,找到 Dependencies 标签,里面有各个不同 .NET Framework 版本的 .NET Framework 引用包。
  2. 点开你项目需要的那个版本的 .NET Framework 包,然后在页面右边找到 Download package 链接,点它,下下来。
  3. 解压下载下来的 NuGet 包,取出其中的“/build/.NET Framework”文件夹,复制到你的项目里某个位置。
  4. 在你仓库的根目录添加或修改 Directory.Build.props 文件,里面添加下面的代码。

Directory.Build.props 文件的新增内容:

1 2 3 4 5 6 7 8 9 10 11 12

<Project> ++ <PropertyGroup> ++ <TargetFrameworkRootPath>$(MSBuildThisFileDirectory)Dependencies</TargetFrameworkRootPath> ++ </PropertyGroup> ++ <ItemGroup Condition=" ('$(TargetFrameworkIdentifier)' == '.NETFramework') And ('$(TargetFrameworkVersion)' == 'v4.5') "> ++ <Reference Include="mscorlib" Pack="false" /> ++ <Reference Include="Microsoft.VisualBasic" Pack="false" Condition="'$(Language)' == 'VB' And '$(UsingMicrosoftNETSdk)' == 'true'" /> ++ </ItemGroup> </Project>

其中:

  1. 如果没有此文件,那么创建一个。
  2. 那个 TargetFrameworkRootPath 的值是 .NETFramework 文件夹的父级文件夹。划重点,你需要确保那个文件夹里面包含我们从 NuGet 包里解压出来的 .NETFramework 完整文件夹。
  3. 后面的 ItemGroup 里的内容,直接照抄上文即可,我也是照抄 Microsoft.NETFramework.ReferenceAssemblies 包里的

用最后的这种方法,算就究级解决方案了。没有这种方案解决不了的问题!如果有,那就是有某项目没受此文件影响,把这段代码拷到那个项目的 csproj 文件里去。

本文会经常更新,请阅读原文: https://blog.walterlv.com/post/support-old-netfx-on-vs2022-or-later.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Visual Studio 2022 升级不再附带 .NET Framework 4.5 这种古老的目标包了,本文帮你装回来
就在北京时间 2021 年 11 月 9 日凌晨,Visual Studio 2022 正式发布了!着急升级的小伙伴兴致勃勃地升级并卸载了原来的 Visual Studio 2019 后,发现自己的几个库项目竟然无法编译通过了。究其原因,是因为我的一些库依旧在支持古老的 .NET Framework 4.5 框架,而 Visual Studio 2022 不再附带如此古老的目标包了。
walterlv
2023/10/23
1.2K0
Visual Studio 2022 升级不再附带 .NET Framework 4.5 这种古老的目标包了,本文帮你装回来
将 .NET Core 项目打一个最简单的 NuGet 源码包,安装此包就像直接把源码放进项目一样
2018-06-20 01:22
walterlv
2018/09/18
1.1K0
将 .NET Core 项目打一个最简单的 NuGet 源码包,安装此包就像直接把源码放进项目一样
Roslyn 使用 Directory.Build.props 文件定义编译
本文告诉大家 Directory.Build.props 是什么有什么优点?如何使用 Directory.Build.props 文件定义编译
林德熙
2018/09/19
1.3K0
Roslyn 使用 Directory.Build.props 文件定义编译
Visual Studio 智能提示错误修复案例
代码能够编译通过,但是 Visual Studio 编辑器会提示错误,找不到类型引用之类的,一堆红线,写代码还没有了智能提示。
jgrass
2024/12/25
2760
Visual Studio 智能提示错误修复案例
dotnet 打包 NuGet 的配置属性大全整理
本文整理 dotnet 打包 CBB 组件为 NuGet 包时可以使用的配置的各个属性
林德熙
2023/04/07
1.6K0
将基于 .NET Framework 的 WPF 项目迁移到基于 .NET Core 3
在 Connect(); 2018 大会上,微软发布了 .NET Core 3 Preview,以及基于 .NET Core 3 的 WPF;同时还发布了 Visual Studio 2019 预览版。你可以基于 .NET Core 3 创建 WPF 程序。不过,如果你已经有基于 .NET Framework 的 WPF 项目,那么如何快速迁移到基于 .NET Core 的版本呢?
walterlv
2023/10/22
4300
将基于 .NET Framework 的 WPF 项目迁移到基于 .NET Core 3
从零开始制作 NuGet 源代码包(全面支持 .NET Core / .NET Framework / WPF 项目)
默认情况下,我们打包 NuGet 包时,目标项目安装我们的 NuGet 包会引用我们生成的库文件(dll)。除此之外,我们也可以专门做 NuGet 工具包,还可以做 NuGet 源代码包。然而做源代码包可能是其中最困难的一种了,目标项目安装完后,这些源码将直接随目标项目一起编译。
walterlv
2023/10/23
1.3K0
从零开始制作 NuGet 源代码包(全面支持 .NET Core / .NET Framework / WPF 项目)
VisualStudio 如何在 NuGet 包里面同时包含 DEBUG 和 RELEASE 的库
我在开发的时候需要使用到一些 DEBUG 库进行调试,但是我的库是通过 NuGet 给用户的,如果在 NuGet 里面使用到了 DEBUG 的库那么会让代码的运行效率降低。于是我就找到一个方法,可以在 NuGet 同时打包调试和发布的包,这样在用户调试的时候就可以使用调试的代码
林德熙
2019/04/22
2.1K0
VisualStudio 如何在 NuGet 包里面同时包含 DEBUG 和 RELEASE 的库
理解 C# 项目 csproj 文件格式的本质和编译流程
发布于 2018-05-10 00:13 更新于 2018-08-12 08:11
walterlv
2018/09/18
2.8K0
理解 C# 项目 csproj 文件格式的本质和编译流程
C# 如何部分加载“超大”解决方案中的部分项目
在有的特有的项目环境下,团队会将所有的项目使用同一个解决方案进行管理。这种方式方面了管理,但是却会导致解决方案变得非常庞大,导致加载时间过长。那么,如何部分加载解决方案中的部分项目呢?就让我们来借用微软退出的 slngen 工具来体验一下部分加载解决方案中的部分项目吧。
newbe36524
2023/08/23
4000
dotnet 构建 SourceRoot items must include at least one top-level item when DeterministicSourcePaths is
在使用 dotnet 构建的时候提示 error : SourceRoot items must include at least one top-level (not nested) item when DeterministicSourcePaths is true 构建失败
林德熙
2020/10/15
7530
如何让 .NET 程序脱离系统安装的 .NET 运行时独立运行?除了 Self-Contained 之外还有更好方法!谈 dotnetCampus.AppHost 的工作原理
从 .NET Core 3 开始,.NET 应用就支持独立部署自己的 .NET 运行时。可以不受系统全局安装的 .NET 运行时影响,特别适合国内这种爱优化精简系统的情况……鬼知道哪天就被优化精简了一个什么重要 .NET 运行时组件呢!然而,如果你的项目会生成多个 exe 程序,那么他们每个独立发布时,互相之间的运行时根本不互通。即便编译时使用完全相同的 .NET 框架(例如都设为 net6.0),最终也无法共用运行时文件。
walterlv
2023/10/23
9440
如何让 .NET 程序脱离系统安装的 .NET 运行时独立运行?除了 Self-Contained 之外还有更好方法!谈 dotnetCampus.AppHost 的工作原理
WPF 程序的编译过程
基于 Sdk 的项目进行编译的时候,会使用 Sdk 中附带的 props 文件和 targets 文件对项目进行编译。Microsoft.NET.Sdk.WindowsDesktop 的 Sdk 包含 WPF 项目的编译过程。
walterlv
2023/10/22
5420
WPF 程序的编译过程
Roslyn 使用 Directory.Build.props 管理多个项目配置
在一些大项目需要很多独立的仓库来做,每个仓库之间都会有很多相同的配置,本文告诉大家如何通过 Directory.Build.props 管理多个项目配置
林德熙
2019/03/13
6550
Roslyn 使用 Directory.Build.props 管理多个项目配置
让一个 csproj 项目指定多个开发框架
发布于 2018-01-21 03:28 更新于 2018-08-31 09:56
walterlv
2018/09/18
1.1K0
让一个 csproj 项目指定多个开发框架
解读 Microsoft.NET.Sdk 的源码,你能定制各种奇怪而富有创意的编译过程
发布于 2018-06-30 05:55 更新于 2018-08-12 08:05
walterlv
2018/09/18
1.4K0
解读 Microsoft.NET.Sdk 的源码,你能定制各种奇怪而富有创意的编译过程
以1个具体接口为例来展示腾讯云.NET SDK的使用
【.NET Core和ASP.NET Core】是什么,它们跟【.NET Framework和ASP.NET】的区别是什么,为什么要选用前者
Windows技术交流
2020/03/13
1.9K0
【实验手册】使用Visual Studio Code 开发.NET Core应用程序
.NET Core with Visual Studio Code 目录 概述... 2 先决条件... 2 练习1: 安装和配置.NET Core以及Visual Studio Code 扩展... 2 任务1:安装Visual Studio Code和.NET Core. 2 任务2:安装插件... 4 练习2:使用命令行界面构建. NET Core应用程序... 5 练习3:使用 Visual Studio Code和 Omnisharp 调试 c# 代码... 12 任务1:从VS code启动调试
张善友
2018/01/29
3.7K0
将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj
发布于 2018-01-15 16:04 更新于 2018-09-07 04:40
walterlv
2018/09/18
1.6K0
将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj
制作通过 NuGet 分发的源代码包时,如果目标项目是 WPF 则会出现一些问题(探索篇,含解决方案)
在使用 NuGet 包来分发源代码时,如果目标项目是 WPF 项目,那么会有一大堆的问题。
walterlv
2023/10/22
5900
制作通过 NuGet 分发的源代码包时,如果目标项目是 WPF 则会出现一些问题(探索篇,含解决方案)
推荐阅读
Visual Studio 2022 升级不再附带 .NET Framework 4.5 这种古老的目标包了,本文帮你装回来
1.2K0
将 .NET Core 项目打一个最简单的 NuGet 源码包,安装此包就像直接把源码放进项目一样
1.1K0
Roslyn 使用 Directory.Build.props 文件定义编译
1.3K0
Visual Studio 智能提示错误修复案例
2760
dotnet 打包 NuGet 的配置属性大全整理
1.6K0
将基于 .NET Framework 的 WPF 项目迁移到基于 .NET Core 3
4300
从零开始制作 NuGet 源代码包(全面支持 .NET Core / .NET Framework / WPF 项目)
1.3K0
VisualStudio 如何在 NuGet 包里面同时包含 DEBUG 和 RELEASE 的库
2.1K0
理解 C# 项目 csproj 文件格式的本质和编译流程
2.8K0
C# 如何部分加载“超大”解决方案中的部分项目
4000
dotnet 构建 SourceRoot items must include at least one top-level item when DeterministicSourcePaths is
7530
如何让 .NET 程序脱离系统安装的 .NET 运行时独立运行?除了 Self-Contained 之外还有更好方法!谈 dotnetCampus.AppHost 的工作原理
9440
WPF 程序的编译过程
5420
Roslyn 使用 Directory.Build.props 管理多个项目配置
6550
让一个 csproj 项目指定多个开发框架
1.1K0
解读 Microsoft.NET.Sdk 的源码,你能定制各种奇怪而富有创意的编译过程
1.4K0
以1个具体接口为例来展示腾讯云.NET SDK的使用
1.9K0
【实验手册】使用Visual Studio Code 开发.NET Core应用程序
3.7K0
将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj
1.6K0
制作通过 NuGet 分发的源代码包时,如果目标项目是 WPF 则会出现一些问题(探索篇,含解决方案)
5900
相关推荐
Visual Studio 2022 升级不再附带 .NET Framework 4.5 这种古老的目标包了,本文帮你装回来
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档