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 13, 2017

Just for clarification, the license of this file is "do what the heck you want with it". No copyright, no terms, no nothing. Have fun!

@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