Error: Could not load file or assembly 'Microsoft.Win32Registry' from .NET Standard Library Consumed by .NET Framework Console App

Error: Could not load file or assembly 'Microsoft.Win32Registry' from .NET Standard Library Consumed by .NET Framework Console App

问题

Microsoft.Win32.Registry nuget package 给我带来了很多问题。我们有 .NET Framework 4.7.2 库,它有一个助手 class,它使用该包并且在 .NET Framework 4.7.2 单元测试项目中运行良好。我们最近将库转换为目标 .NET Standard 2.0,现在这个 class 在使用时出现以下错误:

ERROR: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified. File name: 'Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' at NetStandardRegistryLib.RegistryUtil..ctor(String remoteMachineName) at NetStandardRegistryLib.Program.Main(String[] args) in C:\src\Microsoft.Win32.Registry-IssueRepro\FrameworkRegistry\RegistryEditor\Program.cs:line 21

当我查看控制台项目的输出时,我没有在输出中看到 Microsoft.Win32.Registry.dll

使用 ILSpy 并加载我的 .exe - 它似乎会尝试从我的 dotnet 核心安装中解析 .dll,这不会起作用,因为它是一个 .NET Framework 应用程序。

复制

我创建了一个存储库,可以在我的 Windows 2010 机器上为我复制。您可以在这里找到它:https://github.com/TylerNielsen/Microsoft.Win32.Registry-IssueRepro

克隆 repo,然后打开并构建 RegistryEditor 项目。

使用 Powershell 或您最喜欢的编辑器 - 使用三个必需的参数调用该工具 [remoteMachineName] [要设置的环境变量名称] [要在环境变量上设置的值] **

** 注意,这实际上需要一台您可以通过 IP 地址引用的远程机器。出于某种原因,使用 127.0.0.1 对我不起作用,但我不确定为什么。此实用程序的用例是访问远程机器环境变量。

其他注意事项

当我创建 .NET Framework Class 库以用于单元测试并引用相同的 .NET 标准库时 - Microsoft.Win32.Registry 包已包含在内并且该实用程序运行良好。

在您的存储库中,如果您查看这两个 csproj 文件,您会发现它们完全不同。 NetStandardRegistryLib.csproj 是新格式,RegistryEditor.csproj 是旧格式。

您的问题是旧式项目不会传递地解决依赖关系。 RegistryEditor 不会复制它自己的依赖 NetStandardRegistryLib 的依赖。

至少有两种方法可以解决您的问题:

  1. 只需将 Microsoft.Win32.Registry Nuget 包显式添加到 RegistryEditor 项目即可。这将使 Microsoft.Win32.Registry.dll 出现在 RegistryEditor 构建文件夹中。

  2. 将 RegistryEditor.csproj 转换为新格式。它不仅限于 netstandard 构建,您也可以将它用于针对 .Net Framework 版本的构建。而且它确实 传递地解决依赖关系!

这里有一份关于如何进行一般转换的长篇指南https://natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/

由于您的项目比较简单,我已经为您进行了转换。只需将 RegistryEditor.csproj 的内容替换为以下代码即可。它仍然以 net472.

为目标
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
    <AssemblyName>RegistryEditor</AssemblyName>
    <RootNamespace>RegistryEditor</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\NetStandardRegistryLib\NetStandardRegistryLib.csproj" />
  </ItemGroup>
</Project>

请注意,以前在 AssemblyInfo.cs 文件中的几个属性现在由 csproj 文件属性提供,因此您需要从 AssemblyInfo.cs 中删除它们以修复编译错误:

[assembly: AssemblyTitle("RegistryEditor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RegistryEditor")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]