Spa*_*man 2 .net c# registry impersonation .net-3.5
我最近编写了一个模拟用户帐户的应用程序,获取CURRENT_USER注册表项的句柄(使用PInvoke"LoadUserProfile"检索ProfileInfo.hProfile对象)并使用RegistryKey.FromHandle创建注册表项.
参考代码:
using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(hToken))
{
using (SafeRegistryHandle safeHandle = new SafeRegistryHandle(hProfile, true))
{
using (RegistryKey impersonatedUserHkcu = RegistryKey.FromHandle(safeHandle, RegistryView.Default))
{
// Do something with registry
}
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码运行良好(在Windows 7中运行),但使用仅支持.NET 4.0及更高版本的对象/方法(SafeRegistryHandle,RegistryKey.FromHandle(),RegistryView枚举).
现在,我需要使这个应用程序与.NET 3.5兼容,以便在具有Windows XP的机器中使用它,并且无法安装.NET Framework 4.0.
我可以使用.NET 3.5来实现相同的结果吗?(即,对模拟用户的注册表项进行修改).或者确实存在只有-.NET4对象的某种源代码?
经过几天的研究,以及MSDN社区对同一问题的帮助,我找到了完成我需求的方法.
最初的建议是使用Win Api功能RegOpenKeyEx(参见P/Invoke网站获取信息和样本); 但根据这篇MSDN文章,我发现了这一点
如果您的服务或应用程序模拟了不同的用户,请不要将此功能与HKEY_CURRENT_USER一起使用.而是调用RegOpenCurrentUser函数.
最后,要走的路是RegOpenCurrentUser功能.(遗憾的是,在P/Invoke网站上仍然没有此功能的痕迹,但您可以在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;
}
Run Code Online (Sandbox Code Playgroud)
这就是我用它来获取注册表的方法:
IntPtr localRegistryHandle = GetImpersonateUserRegistryHandle(TestRegistryAccess.RegistrySecurity.KEY_ALL_ACCESS);
using(RegistryKey localRegistry = _pointerToRegistryKey(localRegistryHandle, true, true))
{
// do something with local registry
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2114 次 |
| 最近记录: |