首页 文章

将注册表写入hkey_current_user而不是hkey_users

提问于
浏览
3

我尝试将注册表子项及其对应的值写入注册表,如下所示:

Microsoft.Win32.RegistryKey mykey;
mykey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\Windows\\Muhil Software");
mykey.SetValue("Muhil", "TEST");
mykey.close();

如您所见,我使用 CurrentUser 将值写入 HKEY_CURRENT_USERHKEY_CURRENT_USER 中没有任何内容 . 然后我检查了 HKEY_USERS 中的子项,发现密钥写在那里 .

1 回答

  • 2

    您的安装程序不会在登录的用户会话下运行,而是在本地系统会话下运行 . 这就解释了为什么 HKCU 指向另一个注册表配置单元 .

    要打开已登录用户的注册表项,您需要打开此注册表项 HKU/<LOGGED_ON_USER_SID> . 借助Windows Session API,您可以获得此SID(安全标识符) .

    您可以使用 Microsoft.Win32.Registry.Users 而不是 Microsoft.Win32.Registry.CurrentUser 并使用用户SID打开正确的用户密钥 .

    您可以在stackoverflow上找到有关如何获取当前登录SID的几个主题,例如How to get a Unique ID for the current user's logon session in windows - c#

    UPDATE : A sample code that is able to get the logged-on user SID string, It will only work in the system session because it requires special privileges SE_TCB_NAME. There is no error handling for simplicity

    static void Main(string[] args)
    {
        Microsoft.Win32.RegistryKey mykey;
        mykey = Microsoft.Win32.Registry.Users.CreateSubKey(GetLoggedOnUserSID() + "\\Software\\Microsoft\\Windows\\Muhil Software");
        mykey.SetValue("Muhil", "TEST");
        mykey.Close();
    }
    
    enum TokenInformationClass
    {
        TokenOwner = 4,
    }
    
    struct TokenOwner
    {
        public IntPtr Owner;
    }
    
    [DllImport("advapi32.dll", EntryPoint = "GetTokenInformation", SetLastError = true)]
    static extern bool GetTokenInformation(
        IntPtr tokenHandle,
        TokenInformationClass tokenInformationClass,
        IntPtr tokenInformation,
        int tokenInformationLength,
        out int ReturnLength);
    
    [DllImport("kernel32.dll")]
    private static extern UInt32 WTSGetActiveConsoleSessionId();
    
    [DllImport("wtsapi32.dll", SetLastError = true)]
    static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
    
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern bool ConvertSidToStringSid(IntPtr sid, [In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
    
    static string GetLoggedOnUserSID()
    {
        IntPtr tokenOwnerPtr;
        int tokenSize;
        IntPtr hToken;
    
        // Get a token from the logged on session
        // !!! this line will only work within the SYSTEM session !!!
        WTSQueryUserToken(WTSGetActiveConsoleSessionId(), out hToken); 
    
        // Get the size required to host a SID
        GetTokenInformation(hToken, TokenInformationClass.TokenOwner, IntPtr.Zero, 0, out tokenSize);
        tokenOwnerPtr = Marshal.AllocHGlobal(tokenSize);
    
        // Get the SID structure within the TokenOwner class
        GetTokenInformation(hToken, TokenInformationClass.TokenOwner, tokenOwnerPtr, tokenSize, out tokenSize);
        TokenOwner tokenOwner = (TokenOwner)Marshal.PtrToStructure(tokenOwnerPtr, typeof(TokenOwner));
    
        // Convert the SID into a string
        string strSID = "";
        ConvertSidToStringSid(tokenOwner.Owner, ref strSID);
        Marshal.FreeHGlobal(tokenOwnerPtr);
        return strSID;        
    }
    

相关问题