访问的currentUser注册表项模拟用户 - 使用.NET 3.5的兼容性兼容性、注册表、用户、currentUser

2023-09-04 03:51:57 作者:不舍流年

我最近写了模拟用户帐户的应用程序,得到一个处理CURRENT_USER注册表项(使用的PInvokeLoadUserProfile检索ProfileInfo.hProfile对象),并使用RegistryKey.FromHandle创建注册表项。

I've recently written an application that impersonate user account, get a handle to CURRENT_USER registry key (using PInvoke "LoadUserProfile" to retrieve ProfileInfo.hProfile object) and create registry key using RegistryKey.FromHandle.

参考code:

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
        }
    }
}

这一块code只能从.NET 4.0和更高版本(SafeRegistryHandle,RegistryKey.FromHandle(),RegistryView枚举)支持良好(在Windows 7上运行),但利用的对象/方法。

This piece of code works good (run in Windows 7), but made use of objects/methods supported only from .NET 4.0 and greater (SafeRegistryHandle, RegistryKey.FromHandle(), RegistryView enum).

现在,我需要这个应用程序与.NET 3.5兼容,使用它在一台机器使用Windows XP和没有机会来安装.NET Framework 4.0。

Now, I need to make this application compatible with .NET 3.5, for use it in a machine with Windows XP and no possibilities to install .NET Framework 4.0.

是否有任何等效对象,我可以使用.NET 3.5使用来完成同样的结果呢? (即,使修改注册表项模拟的用户)。 还是确实存在某种源$ C ​​$的only-.NET 4物体CS?

Are there any equivalent objects I can use with .NET 3.5 to accomplish the same result? (that is, make modification to registry key for impersonated user). Or does exist some kind of source codes of the only-.NET 4 objects?

推荐答案

在研究日,和帮助MSDN社区对同一问题,我发现跟着来完成我的需要的方式。

After days of research, and help from MSDN community to the same question, I've found the way to follow to accomplish my needs.

最初的建议是用Win API函数 RegOpenKeyEx的(见的的P / Invoke网站的相关信息和样本);但根据这个MSDN文章< /一>,我发现

The initial suggestion was to use Win Api function RegOpenKeyEx (see P/Invoke website for infos and samples); but according to this MSDN article, I've found that

如果您的服务或应用程序模仿不同的用户,千万不要使用此功能HKEY_CURRENT_USER。相反,调用RegOpenCurrentUser功能。

If your service or application impersonates different users, do not use this function with HKEY_CURRENT_USER. Instead, call the RegOpenCurrentUser function.

最后,要走的路是 RegOpenCurrentUser 功能。 (遗憾的是还是有没有痕迹的P / Invoke的网站这个功能,但你可以找到一些相关信息的在MSDN )

Finally, the way to go is RegOpenCurrentUser function. (unfortunately there's still no trace of this function on P/Invoke website, but you can find some infos 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;
}

这是我如何使用它来获取注册表:

And this is how I use it to get registry:

IntPtr localRegistryHandle = GetImpersonateUserRegistryHandle(TestRegistryAccess.RegistrySecurity.KEY_ALL_ACCESS);

using(RegistryKey localRegistry = _pointerToRegistryKey(localRegistryHandle, true, true))
{
    // do something with local registry
}