15

I'm trying to grant Write access to my application's registry settings to everyone or all users of a machine during the install process.

My application does not have the appropriate permissions directly after install without requiring an administrator to grant them even though the keys and values exists, they cannot be updated? I've the snippet below, but the installer is failing due to Unauthorized access / access denied. I think I'm on the right track...

How can I resolve the permissions issue without requiring manual attention? Is there a better approach? I'm attempting to replace an additional installer with the Visual Studio setup by adding this functionality.

    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);
        }

    }
Jared Knipp
  • 5,880
  • 7
  • 44
  • 52
  • 11
    I used your snippet to accomplish something similar... just to let you know, `Registry.LocalMachine.OpenSubKey(key)` should be `Registry.LocalMachine.OpenSubKey(key, true)` (where `true` indicates that the key will be writable). I was running into `UnauthorizedAccessExceptions` without that change. Thanks! – Mark Carpenter Mar 14 '11 at 22:10
  • Thanks for that, Pwninstein! It saved me untold hours of frustration! – B. Clay Shannon-B. Crow Raven Jan 21 '15 at 21:44

4 Answers4

11

I realize this post is a bit old but I figured it was worth commenting on it for anyone that might stumble upon it like I did while trying to figure out a similar issue. You were very close, I just changed two lines of code. The key change is the first one; when opening the key you need to open it as writable. The second change is to append new permissions rather than replacing all permissions...since you are giving everyone full access, you don't really need this change, but if you were adding permissions for single user, you would want to append permissions.

Each change I made first comments out the old line with //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);
}
KevinC
  • 171
  • 2
  • 5
1

The better approach is to put your application settings somewhere that your users will have permission to update.

dkackman
  • 15,179
  • 13
  • 69
  • 123
  • 1
    I agree, but an optimal solution requires bigger refactoring effort. Right now I'm trying to retrofit an application I inherited. – Jared Knipp Jan 27 '10 at 23:27
  • that blows. Are you sure that the installer is running with administrative/elevated privileges? – dkackman Jan 28 '10 at 00:30
  • That is a possibility, my dev/test box is XP. I'll look into that. – Jared Knipp Jan 28 '10 at 16:36
  • Finally had time to move the settings out, it wasn't too bad, I extended System.Configuration.SettingsProvider to create a custom provider to save standard settings remotely and to the registry. – Jared Knipp Sep 15 '10 at 15:26
1

I ended up taking a different and better approach by switching to Wix 3.0. Using the Wix installer I'm able more easily customize and expand my install.

Add Wix Util Extension namespace:

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

Wix Sample for registry permissions:

<!-- 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> 
    ...
Jared Knipp
  • 5,880
  • 7
  • 44
  • 52
1

try this

 new   System.Security.Permissions.RegistryPermission(System.Security.Permissions.PermissionState.Unrestricted).Assert();
try
{
//Your code
}catch
{
}finally
{
       System.Security.Permissions.RegistryPermission.RevertAssert();
}
Tanmay Nehete
  • 2,138
  • 4
  • 31
  • 42