經過幾天的研究,and help from MSDN community to the same question,我找到了滿足我的需求的方式。
最初的建議是使用Win Api函數RegOpenKeyEx
(有關信息和示例,請參見P/Invoke website);但根據this MSDN article,我發現
如果您的服務或應用程序模擬不同的用戶,請不要將此函數與HKEY_CURRENT_USER一起使用。相反,調用RegOpenCurrentUser函數。
最後,要走的路是RegOpenCurrentUser
函數。 (遺憾的是還是有沒有上的P/Invoke網站這個功能的痕跡,但你可以找到一些相關信息on MSDN)
這是我當前如何定義它:
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenCurrentUser(int samDesired, out IntPtr phkResult);
public enum RegistrySecurity
{
KEY_ALL_ACCESS = 0xF003F,
KEY_CREATE_LINK = 0x0020,
KEY_CREATE_SUB_KEY = 0x0004,
KEY_ENUMERATE_SUB_KEYS = 0x0008,
KEY_EXECUTE = 0x20019,
KEY_NOTIFY = 0x0010,
KEY_QUERY_VALUE = 0x0001,
KEY_READ = 0x20019,
KEY_SET_VALUE = 0x0002,
KEY_WOW64_32KEY = 0x0200,
KEY_WOW64_64KEY = 0x0100,
KEY_WRITE = 0x20006,
}
public IntPtr GetImpersonateUserRegistryHandle(RegistrySecurity _access)
{
IntPtr safeHandle = new IntPtr();
int result = RegOpenCurrentUser((int)_access, out safeHandle);
return safeHandle;
}
/// <summary>
/// Get a registry key from a pointer.
/// </summary>
/// <param name="hKey">Pointer to the registry key</param>
/// <param name="writable">Whether or not the key is writable.</param>
/// <param name="ownsHandle">Whether or not we own the handle.</param>
/// <returns>Registry key pointed to by the given pointer.</returns>
public RegistryKey _pointerToRegistryKey(IntPtr hKey, bool writable, bool ownsHandle)
{
//Get the BindingFlags for private contructors
System.Reflection.BindingFlags privateConstructors = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
//Get the Type for the SafeRegistryHandle
Type safeRegistryHandleType =
typeof(Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid).Assembly.GetType("Microsoft.Win32.SafeHandles.SafeRegistryHandle");
//Get the array of types matching the args of the ctor we want
Type[] safeRegistryHandleCtorTypes = new Type[] { typeof(IntPtr), typeof(bool) };
//Get the constructorinfo for our object
System.Reflection.ConstructorInfo safeRegistryHandleCtorInfo = safeRegistryHandleType.GetConstructor(
privateConstructors, null, safeRegistryHandleCtorTypes, null);
//Invoke the constructor, getting us a SafeRegistryHandle
Object safeHandle = safeRegistryHandleCtorInfo.Invoke(new Object[] { hKey, ownsHandle });
//Get the type of a RegistryKey
Type registryKeyType = typeof(RegistryKey);
//Get the array of types matching the args of the ctor we want
Type[] registryKeyConstructorTypes = new Type[] { safeRegistryHandleType, typeof(bool) };
//Get the constructorinfo for our object
System.Reflection.ConstructorInfo registryKeyCtorInfo = registryKeyType.GetConstructor(
privateConstructors, null, registryKeyConstructorTypes, null);
//Invoke the constructor, getting us a RegistryKey
RegistryKey resultKey = (RegistryKey)registryKeyCtorInfo.Invoke(new Object[] { safeHandle, writable });
//return the resulting key
return resultKey;
}
這是我如何使用它來獲取註冊表:
IntPtr localRegistryHandle = GetImpersonateUserRegistryHandle(TestRegistryAccess.RegistrySecurity.KEY_ALL_ACCESS);
using(RegistryKey localRegistry = _pointerToRegistryKey(localRegistryHandle, true, true))
{
// do something with local registry
}
這是缺少你如何得到你的'WindowsImpersonationContext'和你登錄你的用戶併發送憑據的地方。一個完整的例子本來不錯。如果你可以使用'RegistryKey',我不知道你爲什麼需要一個函數來返回一個密鑰。只要執行'RegistryKey key = Registry.CurrentUser.OpenSubKey(KEY_STR,true);',其中'KEY_STR'是你的路徑。你並不需要所有這些,而且'SafeRegistryHandle'和所有。過度殺毒,即使是.NET 3.5。 – vapcguy 2017-02-22 22:48:05