So far I have the below which is taken from
http://www.danielmoth.com/Blog/volatile-registrykey.aspx
public static class RegistryHelper
{
public static RegistryKey CreateVolatileSubKey(RegistryKey rk, string subkey, RegistryKeyPermissionCheck permissionCheck)
{
var rk2 = rk.GetType();
const BindingFlags bfStatic = BindingFlags.NonPublic | BindingFlags.Static;
const BindingFlags bfInstance = BindingFlags.NonPublic | BindingFlags.Instance;
rk2.GetMethod("ValidateKeyName", bfStatic).Invoke(null, new object[] { subkey });
rk2.GetMethod("ValidateKeyMode", bfStatic).Invoke(null, new object[] { permissionCheck });
rk2.GetMethod("EnsureWriteable", bfInstance).Invoke(rk, null);
subkey = (string)rk2.GetMethod("FixupName", bfStatic).Invoke(null, new object[] { subkey });
if (!(bool)rk2.GetField("remoteKey", bfInstance).GetValue(rk))
{
var key = (RegistryKey)rk2.GetMethod("InternalOpenSubKey", bfInstance, null, new[] { typeof(string), typeof(bool) }, null).Invoke(rk, new object[] { subkey, permissionCheck != RegistryKeyPermissionCheck.ReadSubTree });
if (key != null)
{
rk2.GetMethod("CheckSubKeyWritePermission", bfInstance).Invoke(rk, new object[] { subkey });
rk2.GetMethod("CheckSubTreePermission", bfInstance).Invoke(rk, new object[] { subkey, permissionCheck });
rk2.GetField("checkMode", bfInstance).SetValue(key, permissionCheck);
return key;
}
}
rk2.GetMethod("CheckSubKeyCreatePermission", bfInstance).Invoke(rk, new object[] { subkey });
int lpdwDisposition;
IntPtr hkResult;
var srh = Type.GetType("Microsoft.Win32.SafeHandles.SafeRegistryHandle");
var temp = rk2.GetField("hkey", bfInstance).GetValue(rk);
var rkhkey = (SafeHandleZeroOrMinusOneIsInvalid)temp;
var getregistrykeyaccess = (int)rk2.GetMethod("GetRegistryKeyAccess", bfStatic, null, new[] { typeof(bool) }, null).Invoke(null, new object[] { permissionCheck != RegistryKeyPermissionCheck.ReadSubTree });
var errorCode = RegCreateKeyEx(rkhkey, subkey, 0, null, 1, getregistrykeyaccess, IntPtr.Zero, out hkResult, out lpdwDisposition);
var keyNameField = rk2.GetField("keyName", bfInstance);
var rkkeyName = (string)keyNameField.GetValue(rk);
if (errorCode == 0 && hkResult.ToInt32() > 0)
{
var rkremoteKey = (bool)rk2.GetField("remoteKey", bfInstance).GetValue(rk);
var hkResult2 = srh.GetConstructor(BindingFlags.Instance开发者_如何学运维 | BindingFlags.NonPublic, null, new[] { typeof(IntPtr), typeof(bool) }, null).Invoke(new object[] { hkResult, true });
var key2 = (RegistryKey)rk2.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { hkResult2.GetType(), typeof(bool), typeof(bool), typeof(bool), typeof(bool) }, null).Invoke(new[] { hkResult2, permissionCheck != RegistryKeyPermissionCheck.ReadSubTree, false, rkremoteKey, false });
rk2.GetMethod("CheckSubTreePermission", bfInstance).Invoke(rk, new object[] { subkey, permissionCheck });
rk2.GetField("checkMode", bfInstance).SetValue(key2, permissionCheck);
if (subkey.Length == 0)
{
keyNameField.SetValue(key2, rkkeyName);
}
else
{
keyNameField.SetValue(key2, rkkeyName + @"\" + subkey);
}
key2.Close();
return rk.OpenSubKey(subkey, true);
}
if (errorCode != 0)
rk2.GetMethod("Win32Error", bfInstance).Invoke(rk, new object[] { errorCode, rkkeyName + @"\" + subkey });
return null;
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
private static extern int RegCreateKeyEx(SafeHandleZeroOrMinusOneIsInvalid hKey, string lpSubKey, int reserved, string lpClass, int dwOptions, int samDesigner, IntPtr lpSecurityAttributes, out IntPtr hkResult, out int lpdwDisposition);
}
Which works but is fairly ugly. Is there a better way?
If you are using .NET 4, you can take advantage of the new RegistryOptions enumeration to create a volatile key using the normal .NET APIs.
精彩评论