Skip to content

Instantly share code, notes, and snippets.

@ygoe
Created July 20, 2017 08:56
Show Gist options
  • Save ygoe/bb776fac530176b08519a5314d53fcb6 to your computer and use it in GitHub Desktop.
Save ygoe/bb776fac530176b08519a5314d53fcb6 to your computer and use it in GitHub Desktop.
A class that provides Windows registry access for .NET Framework (define NETFULL) and .NET Standard 1.6 (define NETSTANDARD) projects through P/Invoke.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32;
namespace MyNamespace
{
internal class WindowsRegistry
{
/// <summary>
/// Reads a Windows registry value. This method does nothing if not running on Windows.
/// </summary>
/// <param name="root">The registry hive: "HKLM" or "HKCU".</param>
/// <param name="key">The path of the key to read the value from.</param>
/// <param name="value">The value to read.</param>
/// <returns>The read value if it exists and is a string; otherwise, null.</returns>
public string GetStringValue(string root, string key, string value)
{
#if NETFULL
RegistryKey rootKey;
switch (root)
{
case "HKLM":
rootKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
break;
case "HKCU":
rootKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
break;
default:
throw new InvalidOperationException($"Registry root key {root} unknown.");
}
var regKey = rootKey.OpenSubKey(key);
if (regKey != null)
{
object obj = regKey.GetValue(value);
regKey.Close();
if (obj is string)
{
return (string)obj;
}
}
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
UIntPtr rootKey;
switch (root)
{
case "HKLM":
rootKey = HKEY_LOCAL_MACHINE;
break;
case "HKCU":
rootKey = HKEY_CURRENT_USER;
break;
default:
throw new InvalidOperationException($"Registry root key {root} unknown.");
}
UIntPtr keyHandle;
if (RegOpenKeyEx(rootKey, key, 0, KEY_READ | KEY_WOW64_64KEY, out keyHandle) == 0)
{
RegistryValueKind kind;
var sb = new StringBuilder(1000);
int length = sb.Capacity;
bool found = RegQueryValueEx(keyHandle, value, 0, out kind, sb, ref length) == 0;
RegCloseKey(keyHandle);
if (found)
return sb.ToString();
}
}
#endif
return null;
}
#region Registry interop
#if !NETFULL
[DllImport("advapi32.dll")]
private static extern int RegOpenKeyEx(
UIntPtr hKey,
string subKey,
int ulOptions,
int samDesired,
out UIntPtr hkResult);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegCloseKey(
UIntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern uint RegQueryValueEx(
UIntPtr hKey,
string lpValueName,
int lpReserved,
out RegistryValueKind lpType,
IntPtr lpData,
ref int lpcbData);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern uint RegQueryValueEx(
UIntPtr hKey,
string lpValueName,
int lpReserved,
out RegistryValueKind lpType,
StringBuilder lpData,
ref int lpcbData);
private static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
private static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);
private const int KEY_READ = 0x20019;
private const int KEY_WOW64_64KEY = 0x0100;
private enum RegistryValueKind
{
None = 0,
String = 1,
ExpandString = 2,
Binary = 3,
DWord = 4,
DWordBE = 5,
Link = 6,
MultiString = 7
}
#endif
#endregion Registry interop
}
}
@ygoe
Copy link
Author

ygoe commented Nov 19, 2017

Here's a new compatibility package from Microsoft that might serve the same purpose as this class: Windows Compatibility Pack for .NET Core

https://blogs.msdn.microsoft.com/dotnet/2017/11/16/announcing-the-windows-compatibility-pack-for-net-core/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment