c# - 如何以编程方式将注册表项的所有权授予管理员?

原文 标签 c# .net windows permissions registry

我将一些计算机升级到Windows 10时遇到了一个奇怪的问题,其中RuntimeBroker上的错误权限导致了问题。我发现a solution online建议更改权限(首先在注册表中,然后在DCOM配置中),并且我试图编写一个小型.NET应用程序来自动执行该过程。

目前,相关注册表项的所有者是NT SERVICE\TrustedInstaller,我正在尝试将其更改为COMPUTER\Administrators。我有一个简单的WPF应用程序,requestedExecutionLevel设置为“requireAdministrator”,但是我仍然遇到问题。这是一段代码来说明问题:

using System.Security.AccessControl;
using System.Security.Principal;
using Microsoft.Win32;

namespace PermissionFixer
{
    public class Fixer
    {
        public void Fix()
        {
            var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID\{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", true);
            if (subKey != null)
            {
                var admins = new NTAccount("Administrators");
                var ac = subKey.GetAccessControl();
                ac.SetOwner(admins);
                ac.AddAccessRule(new RegistryAccessRule(admins, RegistryRights.FullControl, AccessControlType.Allow));
                subKey.SetAccessControl(ac);
            }
        }
    }
}

麻烦在于,它甚至在碰到“不允许请求的注册表访问权限”的OpenSubKey()之前,都没有超过对SecurityException的调用。我认为这是因为管理员还没有访问权限(请记住它属于TrustedInstaller),但是这有点麻烦。奇怪的是,当我手动使用regedit时,我可以将所有者更改为Administrators,而且我很确定我的regedit实例以Administrators身份运行。

如何在.NET中使它正常工作?

最佳答案

我已经弄清楚了,幸运的是,可以使用.NET类来实现。这是您必须调用OpenSubKey的方式:

var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID\{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);

然后,您必须取消对AddAccessRule()的调用……您必须拥有所有权后才能修改它;并且您必须串行执行这两个操作。因此,首先获取所有权,然后重新打开具有不同访问权限的 key 以添加访问规则。

编辑:我今天发现,您必须首先通过挂接到P/Invoke调用来操纵运行应用程序的 token 。我在another Stack Overflow question中找到了一个称为TokenManipulator的类。在您的项目中包括该类,然后在调用OpenSubKey之前为您的 token 授予Backup,Restore和TakeOwnership特权。因此,您的方法最终将看起来像这样:
try
{
    TokenManipulator.AddPrivilege("SeRestorePrivilege");
    TokenManipulator.AddPrivilege("SeBackupPrivilege");
    TokenManipulator.AddPrivilege("SeTakeOwnershipPrivilege");

    var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID\{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);
    // code to change owner...
}
finally
{
    TokenManipulator.RemovePrivilege("SeRestorePrivilege");
    TokenManipulator.RemovePrivilege("SeBackupPrivilege");
    TokenManipulator.RemovePrivilege("SeTakeOwnershipPrivilege");
}

关于c# - 如何以编程方式将注册表项的所有权授予管理员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38448390/

相关文章:

c# - 委托(delegate)转换的乐趣-> InvalidProgramException

c# - 这是有效的MVP模式实现吗

java - 在Windows上运行但不在Linux上运行的Java代码

c++ - 通过导入库链接的DLL可以在卸载主机DLL之前卸载吗?

c# - 不支持的sourceStream NAUDIO

c# - 析构函数不能保证完成运行吗?

c# - TweetSharp SendTweetWithMediaOptions 示例

.net - VSTO 和 Office 2010

c# - XNA - 键盘文本输入

带有 JRE 检查的 Java 应用程序的 Windows exe 启动器