ror*_*.ap 8 .net c# binding .net-core .net-standard
从.NET API 目录中,我了解到Microsoft.Win32.Registry该类是在.NET Standard + Platform Extensions 2.0程序集的包中声明的Microsoft.Win32.Registry, Version=4.1.1.0, PublicKeyToken=b03f5f7f11d50a3a。
我创建了一个面向 .NET Standard 2.0 的类库,这是一个简单的类:
public class NetStandardClass
{
public string GetHklmRegValue()
{
var lmKey = Microsoft.Win32.Registry.LocalMachine;
var softwareKey = lmKey.OpenSubKey("Software");
return "value";
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个 .NET Framework 4.7.2 控制台应用程序,它引用了我上面的类库:
class Program
{
static void Main(string[] args)
{
string value = new ClassLibrary2.NetStandardClass().GetHklmRegValue();
}
}
Run Code Online (Sandbox Code Playgroud)
当我在 Windows 上运行它时,这会引发一个运行时异常:
System.IO.FileNotFoundException: '无法加载文件或程序集 'Microsoft.Win32.Registry, Version= 4.1.3.0 , Culture=neutral, PublicKeyToken= b03f5f7f11d50a3a ' 或其依赖项之一。该系统找不到指定的文件。'
根据我所读到的内容,在这种情况下出现程序集加载问题在某种程度上是一个已知问题。规定的解决方法是启用自动绑定重定向并确保我的 .NET Framework 应用程序使用PackageReference而不是Project.Config. 我已经在我共享上述代码的项目中做到了这一点,但我仍然收到错误消息。什么最让我困惑,虽然是错误的指示.NET Core/.NET Core + Platform Extensions组件(版本= 4.1.3.0,公钥= b03f5f7f11d50a3a),而不是.NET标准(版本= 4.1.1.0,公钥= b03f5f7f11d50a3a)或.NET框架(版本=4.0.0.0, PublicKeyToken=b77a5c561934e089 ) 来自 API 目录的版本:
输出目录中的 Microsoft.Win32.Registry.DLL 进一步证实了这一点:
根据进一步阅读,我可以通过执行以下任一操作来取得一些进展:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>到 .NET Standard 类库项目文件- 或者 -
Microsoft.Win32.RegistryNuGet 包直接添加到我的 .NET Framework 控制台应用程序。这些都会导致加载某个版本的程序集,但随后我得到了一些奇怪的行为:我获得了该LocalMachine属性的 NRE ,这不应该发生。
所以这里是问题:
1.) 既然我的项目是.NET Framework 应用程序,为什么不使用Microsoft.Win32.Registry.NET Framework API 中的类,特别mscorlib是同一个API 目录引用的程序集?
2.) 为什么 GitHub 帖子中的“解决方法”对我不起作用?
3.) 为什么它似乎在寻找程序集的 .NET Core / ... 扩展版本?
4.) 为什么当我显式导出Microsoft.Win32.Registry.NET Standard 类库中的 NuGet程序集或直接引用 .NET Framework 控制台应用程序中的包时,它会导致奇怪的行为 whereMicrosoft.Win32.Registry.LocalMachine为 null,这在 Windows 上绝不应该是这种情况机器?
小智 3
以下答案假设安装了最新版本的 Visual Studio 2019(撰写本文时为 v16.4.3),因为这可能会对结果产生一些影响。
1.) 由于我的项目是 .NET Framework 应用程序,为什么它不使用 .NET Framework API 中的 Microsoft.Win32.Registry 类,特别是相同 API 目录引用的 mscorlib 程序集?
Registry当通过以下任一方式设置项目时,这实际上将使用 v4.0.0.0 mscorlib类:
选项1
选项2 [我认为这是你真正想要的]
这应该很容易重现,但是,可能导致某种问题的原因可能是: - 使用旧版本的 VS2019 - 跳过在 VS 中为 NuGet 打开的绑定重定向设置 - 为 .NET 4.7 关闭自动绑定重定向。 2 项目 - 在包或引用更改后不“重建”解决方案 - 安装/更新 .NET SDK 或 VS2019 更新后不重新启动计算机 - 仍然有一个 packages.config 文件
我还想指出,在上面的选项 1中,我在测试中发现,如果不添加 Microsoft.Windows.Registry 包,它在运行时查找 4.1.1.0 版本的注册表 dll 时会失败。但是,通过首先安装 Microsoft.Windows.Registry 4.7.0,然后卸载它(从而留下两个依赖包 AccessControl 和 Primary.Windows),并且无需重建,我能够使其在查找运行时 4.1.3.0 时失败项目:如果我运行它,它会在运行时失败,4.1.3.0 版本是它正在寻找的版本。重建它会恢复到 4.1.1.0。即使我删除了两个依赖包,这仍然是一样的。注意:如果您只是删除项目中对 dll 的引用,而不是卸载 NuGet 包,这也适用。
2.) 为什么 GitHub 帖子中的“解决方法”对我不起作用?
我感觉发生这种情况是因为您的 VS2019 版本可能比 16.4.3 旧。我发现当我使用旧版本时,PackageReference模式仍然会导致运行时错误。当我将 VS2019 更新到 16.4.3 时(抱歉,我不确定哪个确切的版本真正修复了它),这似乎现在可以工作了。我不确定这是否是与各种 SDK 的某种意外交互(也许有些是最近发布的,但 VS 的旧版本不支持)。如果packages.config 文件仍然存在,也可能是一个问题。
另一个问题可能是受到可能已安装且具有不同库版本要求的其他 NuGet 包的干扰。
3.)为什么它似乎在寻找程序集的.NET Core / ...扩展版本?
在引用 .NET Standard 2.0 的 .NET 4.7.2 项目中(.NET 标准项目默认为 .NET Core 项目),它将利用 .NET Core 框架,而不是 .NET 框架。因此,默认情况下对注册表的任何引用都不可用。您需要 Microsoft.Windows.Registry 包(至少)来允许使用注册表,我相信它能够充当库的 .NET 4.7.2 mscorlib 版本的填充程序(如果可用),但请使用4.1.1.0 版本作为后备(或者 4.1.3.0 版本,如果您从 .NET Core 项目引用)。
4.) 为什么当我显式导出 .NET Standard 类库中的 NuGet Microsoft.Win32.Registry 程序集或直接引用 .NET Framework 控制台应用程序中的包时,会导致 Microsoft.Win32.Registry.LocalMachine 出现奇怪的行为为 null,在 Windows 机器上绝对不应该出现这种情况?
我没有亲自测试过这一点,并且在测试上述内容时也没有遇到这个问题,但我对此的感觉是 dll 可能缺少其依赖的 dll。但进一步考虑一下,如果是这种情况,很可能会导致另一个运行时错误。我认为问题在于它们不打算直接导出,并且在此过程中可能会丢失一些东西。
我还要指出的是,如果您在 Windows 以外的任何平台上运行它,注册表可能会返回为空,因为我认为它不会存在于 Linux 运行时上。
我的总体感觉是,VS 和 .NET Core 在一般引用 .NET Framework 或从 .NET Framework 引用时存在一些问题,并且定期取得进展来改进这一点。
我还发现有一些我没有预料到的令人惊讶的问题。例如,创建 .NET Standard 控制台应用程序、引用 .NET Standard 类库,但无论我在控制台应用程序上安装什么包,仍然会出现运行时错误。您可能会认为完全相同的目标框架无需任何特殊配置即可工作,但事实似乎并非如此。但如果您创建一个 .NET Core 控制台应用程序,它确实可以正常工作。这有点令人费解,但其中总有一个技术解释。
| 归档时间: |
|
| 查看次数: |
1938 次 |
| 最近记录: |