The Microsoft.Win32.Registry nuget package is giving me a lot of issues . We had .NET Framework 4.7.2 library that had a helper class that used that package and worked fine from a .NET Framework 4.7.2 unit test project. We recently converted the library to target .NET Standard 2.0, and now this class breaks when used with the following error:
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
When I look at output of the Console project, I don't see the Microsoft.Win32.Registry.dll
in the output.
Using ILSpy and loading my .exe - it seems it would try to resolve the .dll from my dotnet core installation, which wouldn't work since it's a .NET Framework app.
I've created a repo that reproduces for me on my Windows 2010 machine. You can find it here: https://github.com/TylerNielsen/Microsoft.Win32.Registry-IssueRepro
Clone the repo, then open and build the RegistryEditor
project.
Using Powershell or your favorite editor - call the tool with three required arguments [remoteMachineName] [Environment variable name to set] [Value to set on the environment variable] **
** Note, this actually requires a remote machine you can reference by IP address. For some reason using 127.0.0.1 doesn't work for me, but I'm unsure why. The use case for this utility is for accessing remote machine environment variables.
When I create a .NET Framework Class Library to use for unit tests and reference the same .NET Standard Library - the Microsoft.Win32.Registry
package is included and the utility runs just fine.
In your repo, if you look into both csproj files you'll see they are quite different. The NetStandardRegistryLib.csproj is the new format, the RegistryEditor.csproj is the old one.
Your problem is that old style projects do not resolve dependencies transitively. RegistryEditor will not copy dependencies of its own dependency NetStandardRegistryLib.
There are at least two ways to solve your problem:
Just add Microsoft.Win32.Registry Nuget package to RegistryEditor project explicitly. That'll make the Microsoft.Win32.Registry.dll to appear in the RegistryEditor build folder.
Convert the RegistryEditor.csproj to new format. It's not limited to netstandard builds, you can use it for builds targeting .Net Framework versions as well. And it does resolve dependencies transitively!
Here's a long guide for how to do the conversion in general https://natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/
Since your project is quite simple, I've converted it for you. Just replace the content of RegistryEditor.csproj with the code below. It's still targeting 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>
Note that several properties that used to be in AssemblyInfo.cs file are provided by csproj file properties now, so you need to remove them from AssemblyInfo.cs to fix compilation errors:
[assembly: AssemblyTitle("RegistryEditor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RegistryEditor")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]