使用.NET设置注册表键写入权限

15
我正在尝试在安装过程中向所有用户或机器上的所有用户授予对我的应用程序注册表设置的写访问权限。即使键和值存在,我的应用程序在安装后直接没有适当的权限,需要管理员授权才能更新。我有下面的片段,但由于未经授权的访问/拒绝访问,安装程序失败了。我认为我走在了正确的道路上...
如何解决权限问题而无需手动操作?有更好的方法吗?我正在尝试通过添加此功能来使用Visual Studio设置替换额外的安装程序。
    protected void GrantAllAccessPermission(String key)
    {
        try
        {
            SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
            NTAccount account = sid.Translate(typeof(NTAccount)) as NTAccount;

            // Get ACL from Windows, allow writing to the registry key
            using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(key, true))
            {

                RegistrySecurity rs = new RegistrySecurity();

                // Creating registry access rule for 'Everyone' NT account
                RegistryAccessRule rar = new RegistryAccessRule(
                    account.ToString(),
                    RegistryRights.FullControl,
                    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                    PropagationFlags.None,
                    AccessControlType.Allow);

                rs.AddAccessRule(rar);
                rk.SetAccessControl(rs);
            }

        }
        catch (System.Security.SecurityException ex)
        {
            throw new InstallException(
                String.Format("An exception in GrantAllAccessPermission, security exception! {0}", key),  
                ex);
        }
        catch (UnauthorizedAccessException ex)
        {
            throw new InstallException(
                String.Format("An exception in GrantAllAccessPermission, access denied! {0}", key),  
                ex);
        }

    }

11
我使用了你的代码片段来完成类似的任务......只是想告诉你,Registry.LocalMachine.OpenSubKey(key) 应该改为 Registry.LocalMachine.OpenSubKey(key, true)(其中 true 表示打开可写的键)。如果没有这个更改,我会遇到 UnauthorizedAccessExceptions 异常。谢谢! - Mark Carpenter
谢谢你,Pwninstein!这节省了我无数个小时的挣扎! - B. Clay Shannon-B. Crow Raven
4个回答

11

我意识到这篇文章有点陈旧,但是我认为对于像我一样遇到类似问题的人来说,留下评论是值得的。你非常接近了,只需要更改两行代码。关键的更改是第一个:在打开密钥时,您需要将其作为可写文件打开。第二个更改是追加新权限而不是替换所有权限...既然您给了每个人完全访问权限,您实际上不需要进行此更改,但是如果要添加单个用户的权限,则需要追加权限。

我所做的每个更改都首先注释了旧行,使用// CHANGED:

SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
NTAccount account = sid.Translate(typeof(NTAccount)) as NTAccount;

// Get ACL from Windows

// CHANGED to open the key as writable: using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(key))
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(key, RegistryKeyPermissionCheck.ReadWriteSubTree))
{

        // CHANGED to add to existing security: RegistrySecurity rs = new RegistrySecurity();
    RegistrySecurity rs = rk.GetAccessControl()

    // Creating registry access rule for 'Everyone' NT account
    RegistryAccessRule rar = new RegistryAccessRule(
        account.ToString(),
        RegistryRights.FullControl,
        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
        PropagationFlags.None,
        AccessControlType.Allow);

    rs.AddAccessRule(rar);
    rk.SetAccessControl(rs);
}

1

尝试这个

 new   System.Security.Permissions.RegistryPermission(System.Security.Permissions.PermissionState.Unrestricted).Assert();
try
{
//Your code
}catch
{
}finally
{
       System.Security.Permissions.RegistryPermission.RevertAssert();
}

1

最终我采用了不同且更好的方法,转而使用Wix 3.0。通过使用Wix安装程序,我能够更轻松地定制和扩展我的安装。

添加Wix Util Extension命名空间:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>

注册表权限的Wix示例:

<!-- Registry entries -->
<DirectoryRef Id="TARGETDIR">
  <Component Id="RegistryEntries" Guid="{YOUR-GUID}">

    <!-- Create registry keys and grant user rights -->
    <!-- Add Registry Keys and default values as necessary -->
    <RegistryKey Root="HKLM" Key="$(var.RegKey)" Action="create">
        <util:PermissionEx User="[WIX_ACCOUNT_USERS]"  GenericAll="yes"/>
    </RegistryKey> 
    ...

1
更好的方法是将应用程序设置放在用户有权限更新的地方。

1
我同意,但是最优解需要更大的重构工作。现在我正在尝试改造一个我继承的应用程序。 - Jared Knipp
你确定安装程序正在以管理员/提升的权限运行吗?这可能是问题所在。 - dkackman
这是有可能的,我的开发/测试电脑是XP。我会调查一下。 - Jared Knipp
终于有时间将设置移出来了,这并不太难,我扩展了System.Configuration.SettingsProvider以创建一个自定义提供程序,以便远程保存标准设置和注册表。 - Jared Knipp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接