我当前使用的 Windows 服务有问题。基本上,我将一些值存储在
HKCU
注册表中(来自以管理员身份运行的 GUI 工具),并从该 GUI 中启动一项服务。该服务使用 SYSTEM
帐户来运行,我相信这是我的问题 - 我无法访问服务内使用 GUI 工具存储的注册表项,因为它指向不同的 HKCU
!
如何“重定向”服务以使用存储该服务的用户的
HKCU
? (实际上,我可以将用户名传递给服务,或者 SID
如果有人告诉我如何在 GUI 中检索它,但我不知道应该使用什么来 “更改” 用户指向正确的一个)
我使用静态类来访问注册表,GUI和服务都使用它,检索基键的函数是(
rootKey
是保存子键名称的字符串变量):
private static RegistryKey GetBaseKey(bool writable = false)
{
try
{
RegistryKey reg = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
RegistryKey rk = reg?.OpenSubKey("SOFTWARE", writable)?.OpenSubKey(rootKey, writable);
return rk;
}
catch (Exception ex)
{
// handle exceptions later
}
return null;
}
我找到了
WindowsIdentity
类,它可以为当前用户提供句柄(AccessToken
),我是否应该将其作为参数传递给我的服务并使用此句柄来模拟服务内部?
我做了一些事情,但没有用。我尝试过的:
CurrentUserToken = WindowsIdentity.GetCurrent().Token; // to get current identity token
然后用
ServiceController.Start
我添加了 CurrentUserToken.ToString()
作为一个论点。在我的服务中,我使用传递的值初始化了RegistryUserToken (IntPtr)
,但我陷入了困境:
WindowsIdentity RegUser = new WindowsIdentity(RegistryUserToken)
抛出异常:
模拟令牌无效 - 无法复制
我对
AccessToken
的当前实例的 WindowsIdentity
进行了相同的尝试 - 抛出了相同的异常。
我可以走那条路吗?或者我应该尝试一些不同的东西?
我可以给您两个选择:如果您有该用户的凭据,则模拟该用户,或者使用 HKCU 是 HKEY_USERS 下键之一的符号链接的想法。 对于冒充,您可以查看此链接。 如果您知道该用户的 SID,那么您可以在那里找到它。您可以这样获取 SID:
var account = new NTAccount("usernameThatYouNeed");
var identifier = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
var sid = identifier.Value;
我更喜欢模仿。第二个选项适用于您不知道该用户的凭据的情况。 我不喜欢第二个选项,因为它需要管理权限才能写入别人的帐户。
我需要从服务中读取另一个用户的注册表。这就是我让它工作的方式,但在这种情况下我知道确切的用户名。这里的其他答案很有帮助。用户名和路径是您需要的任何内容。
NTAccount f = new NTAccount("yourUserName");
SecurityIdentifier s = (SecurityIdentifier)f.Translate(typeof(SecurityIdentifier));
String sidString = s.ToString();
Microsoft.Win32.RegistryKey OurKey = Microsoft.Win32.Registry.Users;
OurKey = OurKey.OpenSubKey(sidString + "\\SOFTWARE\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Mappings", true);
if (OurKey != null) {
foreach (string Keyname in OurKey.GetSubKeyNames())
{
好吧,我已经设法用不同的方式解决了这个问题。我已将 SID 变量添加到我的注册表类中,如果它不为空,则我打开用户注册表配置单元而不是 HKCU。首先,我使用以下方法检索当前的用户 SID(在我的 GUI 应用程序中):
WindowsIdentity.GetCurrent().User.ToString();
我将其作为参数传递给我的服务并将其设置为注册表类。