将注册表写入 hkey_current_user 而不是 hkey_users

Bla*_*910 5 c# registry

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

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

正如你所看到的,我曾经CurrentUser将值写入HKEY_CURRENT_USER,其中没有任何内容HKEY_CURRENT_USER。然后我检查了子项HKEY_USERS,发现密钥写在那里。

M'h*_*IAS 6

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

为了打开登录用户的注册表项,您需要打开此注册表项HKU/<LOGGED_ON_USER_SID>。您可以通过 Windows 会话 API 获取此 SID(安全标识符)。

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

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

更新:能够获取登录用户 SID 字符串的示例代码,它只能在系统会话中工作,因为它需要特殊权限SE_TCB_NAME。为了简单起见,没有错误处理

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;        
}
Run Code Online (Sandbox Code Playgroud)