14

This should be a fairly simple problem, but for some reason I can't seem to get this to work. All I'd like to do is set the permissions on a given directory to allow full access to all users. Here's the code I have so far:

System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(destinationDirectory);
FileSystemAccessRule fsar = new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow);
DirectorySecurity ds = null;

    if (!di.Exists)
    {
       System.IO.Directory.CreateDirectory(destinationDirectory);
    }

ds = di.GetAccessControl();
ds.AddAccessRule(fsar);

No exceptions get thrown, but nothing happens, either. When I check the directory permissions after the code has been run, I see no changes.

Any ideas?

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
Sonny Boy
  • 7,848
  • 18
  • 76
  • 104
  • Did you try to run code above with UAC disabled? – rkosegi Jan 20 '12 at 16:42
  • 1
    @David - I've tried running the compiled exe as an administrator and it makes no difference to the result. – Sonny Boy Jan 20 '12 at 18:27
  • @rkosegi - How do I do that? Is it a setting in Visual Studio? – Sonny Boy Jan 20 '12 at 18:28
  • 2
    @SonnyBoy No it's a system-wide setting and you should not disable it. If you disable it then you'll be in for a big surprise when your users run your code and find it fails due to lack of privileges. Best not to have surprises like that. – David Heffernan Jan 20 '12 at 18:53

2 Answers2

33

You also need to call SetAccessControl to apply the changes.

ds = di.GetAccessControl();
ds.AddAccessRule(fsar);
di.SetAccessControl(ds); // nothing happens until you do this

It seems that the examples on MSDN are sorely lacking in detail, as discussed here. I hacked the code from this article to get the following which behaves well:

static bool SetAcl()
{
    FileSystemRights Rights = (FileSystemRights)0;
    Rights = FileSystemRights.FullControl;

    // *** Add Access Rule to the actual directory itself
    FileSystemAccessRule AccessRule = new FileSystemAccessRule("Users", Rights,
                                InheritanceFlags.None,
                                PropagationFlags.NoPropagateInherit,
                                AccessControlType.Allow);

    DirectoryInfo Info = new DirectoryInfo(destinationDirectory);
    DirectorySecurity Security = Info.GetAccessControl(AccessControlSections.Access);

    bool Result = false;
    Security.ModifyAccessRule(AccessControlModification.Set, AccessRule, out Result);

    if (!Result)
        return false;

    // *** Always allow objects to inherit on a directory
    InheritanceFlags iFlags = InheritanceFlags.ObjectInherit;
    iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;

    // *** Add Access rule for the inheritance
    AccessRule = new FileSystemAccessRule("Users", Rights,
                                iFlags,
                                PropagationFlags.InheritOnly,
                                AccessControlType.Allow);
    Result = false;
    Security.ModifyAccessRule(AccessControlModification.Add, AccessRule, out Result);

    if (!Result)
        return false;

    Info.SetAccessControl(Security);

    return true;
}
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks, David. Still no luck, though. Is my use of the group "Users" correct for this purpose? I've tried running the exe as administrator and still nothing appears to be happening when I go through Windows and check the permissions on the folder. – Sonny Boy Jan 20 '12 at 21:01
  • 2
    Getting closer. Changing "users" to "Everyone" now added the "Everyone" group to the folder, but the permissions show up blank; nothing granted. – Sonny Boy Jan 20 '12 at 21:32
  • The code is working fine for me even with `"Users"`. That said, I think the full name is `@"BUILTIN\Users"` but it works either way. – David Heffernan Jan 20 '12 at 21:33
  • Working now, thanks! Windows was only showing me the inherited rights from the parent directory, but the rights were still applied. – Sonny Boy Jan 20 '12 at 21:56
  • You need to set PropagationFlags.None to see the permissions in Windows Explorer. – Piedone Aug 16 '14 at 18:09
  • "FileSystemRights"; Similar to this, is there anything to set permission for Folders? – Dinesh Kumar P Jun 25 '15 at 11:58
  • @Dinesh directories and files are handled in the same way – David Heffernan Jun 25 '15 at 12:15
  • That piece of code is great - so glad I found it, and you went to the effort of refining it. I hate to think how long it would have taken to sort the issue out otherwise. – From Orbonia Feb 14 '18 at 19:20
  • Using ModifyAccessRule working, not use AddAccessRule. – Kiquenet May 31 '19 at 03:07
  • 2
    This is a very awkward code. This one is much simpler: https://stackoverflow.com/questions/9108399/how-to-grant-full-permission-to-a-file-created-by-my-application-for-all-users?answertab=active#tab-top – Elmue Mar 27 '20 at 20:03
  • 1
    @Elmue that solution doesn't work for me - "all users" don't get full control. However, this answer and Timothée Lecomte answer's does work (apparently due to the 2 stage permissions set) – Alonzzo2 Apr 20 '20 at 14:18
  • Strange. I use that code in my program and it works perfectly. It sets the permissions of the directory and of all files in it. – Elmue Apr 20 '20 at 23:57
19

David Heffernan answer does not work on a non-English machine, where trying to set the permissions on "Users" fails with an IdentityNotMapped exception. The following code will work everywhere, by using WellKnownSidType.BuiltinUsersSid instead:

static void SetFullControlPermissionsToEveryone(string path)
{
    const FileSystemRights rights = FileSystemRights.FullControl;

    var allUsers = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);

    // Add Access Rule to the actual directory itself
    var accessRule = new FileSystemAccessRule(
        allUsers,
        rights,
        InheritanceFlags.None,
        PropagationFlags.NoPropagateInherit,
        AccessControlType.Allow);

    var info = new DirectoryInfo(path);
    var security = info.GetAccessControl(AccessControlSections.Access);

    bool result;
    security.ModifyAccessRule(AccessControlModification.Set, accessRule, out result);

    if (!result)
    {
        throw new InvalidOperationException("Failed to give full-control permission to all users for path " + path);
    }

    // add inheritance
    var inheritedAccessRule = new FileSystemAccessRule(
        allUsers,
        rights,
        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
        PropagationFlags.InheritOnly,
        AccessControlType.Allow);

    bool inheritedResult;
    security.ModifyAccessRule(AccessControlModification.Add, inheritedAccessRule, out inheritedResult);

    if (!inheritedResult)
    {
        throw new InvalidOperationException("Failed to give full-control permission inheritance to all users for " + path);
    }

    info.SetAccessControl(security);
}