I want to open a registry key that is a symbolic link.
According to Microsoft I need to use REG_OPTION_OPEN_LINK
to open it.
I searched for an option to add it to the OpenSubKey
function but I didn't find an option. There are only fiver overload functions but none of them allow to add an optional parameter:
Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string name)
Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string name, bool writable)
Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string name, RegistryKeyPermissionCheck permissionCheck)
Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string name, RegistryRights rights)
Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string name, RegistryKeyPermissionCheck permissionCheck, RegistryRights rights)
The only way I can think of is to use p\invoke but maybe I am missing it and there is an option in C# classes.
You can't do this with the normal RegistryKey
functions. Having checked in the source code, it seems that the ulOptions
parameter is always passed as 0
.
The only way is to call RegOpenKeyEx
yourself, and pass the resulting SafeRegistryHandle
to RegistryKey.FromHandle
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.ComponentModel;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
static extern int RegOpenKeyExW(SafeRegistryHandle hKey, String lpSubKey,
int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
public static RegistryKey OpenSubKeySymLink(this RegistryKey key, string name, RegistryRights rights = RegistryRights.ReadKey, RegistryView view = 0)
{
const int REG_OPTION_OPEN_LINK = 0x0008;
var error = RegOpenKeyExW(key.Handle, name, REG_OPTION_OPEN_LINK, ((int)rights) | ((int)view), out var subKey);
if (error != 0)
{
subKey.Dispose();
throw new Win32Exception(error);
}
return RegistryKey.FromHandle(subKey); // RegistryKey will dispose subKey
}
It is an extension function, so you can call it on either an existing sub-key, or on one of the main keys, such as Registry.CurrentUser
. Don't forget to put a using
on the returned RegistryKey
:
using (var key = Registry.CurrentUser.OpenSubKeySymLink(@"SOFTWARE\Microsoft\myKey", RegistryRights.ReadKey))
{
// do stuff with key
}