.NET WPF 工程离线迁移完整指南:告别“包降级”与assets文件缺失

一、问题背景

最近需要将一个 WPF 工程从联网开发机完整迁移到一台完全物理隔离的离线设备上。本以为复制整个项目文件夹和 NuGet 包缓存就能搞定,结果在离线电脑上编译时遇到了接二连三的"惊喜":

  • 找不到资产文件 project.assets.json,请运行 NuGet 包还原

  • 检测到包降级: Microsoft.Extensions.Configuration.Abstractions 从 9.0.8 降级到 9.0.0

  • Could not find a part of the path ... microsoft.win32.systemevents.4.7.0.nupkg

历经多次折腾后,终于让项目在离线环境下完美编译运行。现将完整解决思路和最终方案记录于此,希望能帮助到遇到类似问题的朋友。

二、为什么简单的"复制粘贴"会失败?

在理解解决方案之前,先搞清楚三个关键点:

现象 根本原因
project.assets.json 缺失 该文件由 dotnet restore 动态生成,默认不被 git 收录,拷贝时极易遗漏
包降级警告 (NU1605) NuGet 依赖解析遵循就近原则。如果项目直接引用 A v1.0,而另一个间接依赖要求 A ≥ v2.0,NuGet 会选择 v1.0 并发出警告
找不到具体的 .nupkg 离线包源不完整 ------ 要么拷贝时漏了某些包,要么包的文件夹结构不符合 NuGet 预期

简单复制 binobj 是行不通的,因为那些是编译输出,换了环境必须重新还原和生成。

三、最终有效方案对比

经过实验,下面两种方案都能在离线环境下达成目标。方案一更加推荐(一劳永逸,适合后续继续在离线电脑上开发调试)。

✅ 方案一:使用 packages.lock.json 锁定依赖(推荐)

核心思想:告诉 NuGet "不要分析,就按这个清单恢复"。

步骤 1:在联网电脑上启用锁文件

编辑你的 .csproj 项目文件,在任意 <PropertyGroup> 中添加:

xml

复制

下载

运行

复制代码
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
步骤 2:生成完整的离线包源并锁定版本

在解决方案目录打开终端,执行:

bash

复制

下载

复制代码
# 将所有依赖包下载到 ./offline_packages 文件夹,并生成 packages.lock.json
dotnet restore --packages ./offline_packages --use-lock-file

执行成功后,项目目录下会出现:

  • offline_packages/ 文件夹(内含所有 .nupkg

  • packages.lock.json 文件(记录了精确版本树)

步骤 3:将以下内容一并拷贝到离线电脑

text

复制

下载

复制代码
项目根目录/
├── .sln 解决方案文件
├── 所有 .csproj 项目文件
├── packages.lock.json          ← 必须带上
├── offline_packages/           ← 整个文件夹
├── 源代码文件夹
└── (可选) NuGet.config         ← 见下文
步骤 4:在离线电脑上配置本地包源(二选一)

方法 A:通过 Visual Studio 界面

工具 → NuGet 包管理器 → 程序包管理器设置 → 程序包源

  • 取消勾选 nuget.org 或其他在线源

  • 点击 [+] 添加新源,路径指向 offline_packages 文件夹

方法 B:在项目根目录新建 NuGet.config 文件(推荐,可随工程迁移)

xml

复制

下载

运行

复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />   <!-- 清除所有默认源 -->
    <add key="local-offline" value="./offline_packages" />
  </packageSources>
</configuration>
步骤 5:在离线电脑上执行锁模式还原

打开终端(或 VS 的开发人员命令提示符),进入解决方案目录:

bash

复制

下载

复制代码
dotnet restore --locked-mode --packages ./offline_packages

--locked-mode 会强制要求 packages.lock.json 存在且完全匹配,不会重新解析版本,因此彻底避免了降级警告。

如果一切正常,现在就可以正常 生成解决方案 了。


✅ 方案二:发布为"独立"(Self-contained) 可执行文件

如果你不需要 在离线电脑上修改源码后重新编译,仅仅需要运行程序,这是最省事的办法。

在联网电脑上:

  1. 右键项目 → 发布

  2. 目标选择 文件夹

  3. 设置:

    • 部署模式 = 独立

    • 目标运行时 = win-x64(根据离线电脑系统选择)

    • 勾选 生成单个文件(可选,方便拷贝)

  4. 点击 发布

发布完成后,将 publish 文件夹整个拷贝到离线电脑,直接双击 .exe 即可运行,不需要安装 .NET 运行时,也完全不需要处理任何 NuGet 问题。

缺点:发布文件夹体积较大(包含了运行时和所有依赖),且无法修改源码重新编译。


四、踩坑记录 & 避坑建议

问题现象 解决办法
还原时仍提示缺少 xxx.nupkg 回到联网电脑,用 dotnet restore --packages ./offline_packages 重新下载完整依赖,然后重新拷贝整个文件夹
明明所有包都拷贝了,还是降级 NuGet 默认行为就是"自动协商版本"。必须用 packages.lock.json + --locked-mode 或使用中央包管理(CPM)强制固定版本
dotnet restore 卡住或超时 检查是否误勾选了在线源,或者 NuGet.config 中没有生效。可以用 --source 参数直接指定:dotnet restore --source ./offline_packages
锁文件生成失败 确保项目文件已添加 <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>,然后执行 dotnet restore --use-lock-file

五、总结

你的需求 推荐方案
离线电脑上需要修改代码并重新编译 方案一(锁定依赖 + 本地包源)
离线电脑上仅运行,不改代码 方案二(独立发布)

最终让我成功的是 方案一 ,它绕过了 NuGet 复杂的版本协商机制,让离线环境下的依赖恢复变得确定、可重复。如果你的项目也遇到了类似的 NU1605 降级警告,不妨试试这套"锁文件 + 本地源"的组合拳。


附录:常用命令速查

bash

复制

下载

复制代码
# 联网环境下下载依赖并生成锁文件
dotnet restore --packages ./offline_packages --use-lock-file

# 离线环境下使用锁文件还原(不联网)
dotnet restore --locked-mode --packages ./offline_packages

# 清理所有缓存(谨慎使用)
dotnet nuget locals all --clear

# 查看当前配置的包源
dotnet nuget list source
相关推荐
雨浓YN2 小时前
GKTGD 工业监控系统-04MySQL 与 SQLite 数据库对比(类库:NET8_SQLData)
数据库·sqlite·wpf
Bofu-16 小时前
【内存测试】06-WPF 读取 SMBIOS 实现内存规格自动检测
wpf·p/invoke·windows api·smbios·内存检测·dimm·硬件信息读取
Bofu-19 小时前
【Storage存储测试】07-WPF 通过 WMI + NVMe SMART 实现 SSD 规格自动验证
wpf·nvme·wmi·smart·ssd检测
Bofu-1 天前
【键盘测试】05-WPF 可视化键盘布局配置 + 全局钩子按键检测实战
wpf·键盘测试·全局键盘钩子·scancode·组合键检测
bugcome_com1 天前
WPF 路径动画完全指南:自绘制控件实战
wpf
不会编程的懒洋洋3 天前
WPF 性能优化+异步+渲染
开发语言·笔记·性能优化·c#·wpf·图形渲染·线程
求学中--4 天前
状态管理一文通:@State、@Prop、@Link、@Provide/Consume全解析
人工智能·小程序·uni-app·wpf·harmonyos
雨浓YN5 天前
GKTGD 工业监控系统-00设计文档
wpf