I want to change some folder permissions (set to Read-Only) to ReadWriteExecute!
I wrote this code, but the folder permission is still Read-Only:
private void ChangePermissions(string folder)
{
string userName = Environment.UserName;
FileSystemAccessRule accessRule = new FileSystemAccessRule(userName, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit
| InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow);
DirectoryInfo directoryInfo = new DirectoryInfo(folder);
DirectorySecurity directorySec = directoryInfo.GetAccessControl();
directorySec.AddAccessRule(accessRule);
directoryInfo.SetAccessControl(directorySec);
}
If I want delete this directory with Directory.Delete(folder, true) I get this error message:
"Access to the path 'entries' is denied."
Sure, the permissions are still Read-Only!
What is wrong here?
You could try something like this:
var dirInfo = new DirectoryInfo(folder);
dirInfo.Attributes &= ~FileAttributes.ReadOnly;
This uses the bitwise logical AND operator (&=) to append to the existing Attributes property the inverse of FileAttributes.ReadOnly (because ~ is bitwise NOT).
Related
I need a file to be editable by all local users. The application saves common information to all users in its own folder under ProgramData. I need to guarantee reading and writing to all users, it is so little information that it does not merit the use of a database.
I get the path to the folder from:Path.Combine(Application.CommonAppDataPath, "InfoConfig");
All users can read, write and create in this folder. Except the files that are created by the other users.
I already tried to remove Creator Owner without success. So my last attempt was not to inherit from the container folder and create the permissions from scratch for SYSTEM, Administrators and Users. But it didn't work either, here is my code.
string sharedFolder = Path.Combine(Application.CommonAppDataPath, "InfoConfig");
if (!Directory.Exists(sharedFolder))
{
DirectoryInfo directoryInfo = Directory.CreateDirectory(sharedFolder);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();
directorySecurity.SetAccessRuleProtection(true, false);
FileSystemRights fileSystemRights =
FileSystemRights.FullControl |
FileSystemRights.Modify |
FileSystemRights.Read |
FileSystemRights.Delete;
SecurityIdentifier usersSid =
new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
SecurityIdentifier systemSid =
new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
SecurityIdentifier adminsSid =
new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
FileSystemAccessRule rule =
new FileSystemAccessRule(systemSid, fileSystemRights, AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
rule = new FileSystemAccessRule(adminsSid, fileSystemRights, AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
rule = new FileSystemAccessRule(usersSid, FileSystemRights.Read
| FileSystemRights.Write
| FileSystemRights.Modify,
AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
directoryInfo.SetAccessControl(directorySecurity);
}
It still doesn't work. What am I doing wrong?
I have only considered the below snippet for usersSid, you can tweak it for the other userTypes as well
Have added ObjectSecurity.ModifyAccessRule(AccessControlModification, AccessRule, Boolean) which applies the specified modification to the Discretionary Access Control List (DACL) associated with this ObjectSecurity object (directorySecurity in our instance).
string sharedFolder = Path.Combine(Application.CommonAppDataPath, "InfoConfig");
if (!Directory.Exists(sharedFolder))
{
DirectoryInfo directoryInfo = Directory.CreateDirectory(sharedFolder);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();
directorySecurity.SetAccessRuleProtection(true, false);
FileSystemRights fileSystemRights =
FileSystemRights.FullControl |
FileSystemRights.Modify |
FileSystemRights.Read |
FileSystemRights.Delete;
SecurityIdentifier usersSid =
new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
FileSystemAccessRule rule = new FileSystemAccessRule(usersSid, fileSystemRights,InheritanceFlags.None, PropagationFlags.NoPropagateInherit, AccessControlType.Allow);
directorySecurity.AddAccessRule(rule);
bool result;
directorySecurity.ModifyAccessRule(AccessControlModification.Set, rule, out result);
if (!result)
{
throw new InvalidOperationException("Failed to give full-control permission to all users for path " + path);
}
FileSystemAccessRule inheritedRule = new FileSystemAccessRule(
usersSid,
fileSystemRights,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly,
AccessControlType.Allow);
bool inheritedResult;
directorySecurity.ModifyAccessRule(AccessControlModification.Add, inheritedRule, out inheritedResult);
if (!inheritedResult)
{
throw new InvalidOperationException("Failed to give full-control permission inheritance to all users for " + path);
}
directoryInfo.SetAccessControl(directorySecurity);
}
I'm trying to add the Full Control permission (for a NT service account) to a folder through C#. However, the permission is not set, what I am missing here?
var directoryInfo = new DirectoryInfo(#"C:\Test");
var directorySecurity = directoryInfo.GetAccessControl();
directorySecurity.AddAccessRule(new FileSystemAccessRule("NT Service\\FileMoverService",
FileSystemRights.FullControl, AccessControlType.Allow));
directoryInfo.SetAccessControl(directorySecurity);
You need to specify the inheritance flags:
directorySecurity.AddAccessRule(new FileSystemAccessRule(#"NT Service\FileMoverService",
FileSystemRights.FullControl,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
AccessControlType.Allow));
The method GrantFullControl can be used to set the Full Control permission for a given directory and user.
private static void GrantFullControl(string directoryPath, string username)
{
if (!Directory.Exists(directoryPath))
return;
var directorySecurity = Directory.GetAccessControl(directoryPath);
directorySecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.FullControl,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None,
AccessControlType.Allow));
Directory.SetAccessControl(directoryPath, directorySecurity);
}
Just call the method as shown below.
GrantFullControl(#"C:\Test", #"NT Service\FileMoverService");
I want to be able to set the persmissions for subfolders and files inside a targeted folder for a specific user.
Up until now i found out how to set the permissions for a specific folder. But not for subfolders and files inside the original folder.
After extensive internet search i could not find any clue on how to tackle this problem. Also the windows doku just shows how to set permission for only a directory.
class DirectoryPermissions
{
public static void DirectoryPermissionsMain(string Directory, string Account, string Rights, int Takeaway, string Domain)
{
try
{
string DirectoryName = Directory;
Console.WriteLine("Adding access control entry for " + DirectoryName);
if(Takeaway == 0 && Rights.Equals("Read")){
AddDirectorySecurity(DirectoryName, Domain + #"\" + Account, FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Removing access control entry from " + DirectoryName);
}
MessageBox.Show("Done");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
// Adds an ACL entry on the specified directory for the specified account.
public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(Account,
Rights,
ControlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
}
I hope one of you can point me in the right direction.
You have to add another AccessRule with InheritanceFlags set to ContainerInherit AND ObjectInherit.
To get the permissions to propgate to child folders, the PropagationFlag is set to Inherit only.
Here's an example below
public void PropogateSecurity(string userid,string directory)
{
var myDirectoryInfo = new DirectoryInfo(directory);
var myDirectorySecurity = myDirectoryInfo.GetAccessControl();
myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(userid, FileSystemRights.Modify, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(userid, FileSystemRights.Modify, InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
myDirectoryInfo.SetAccessControl(myDirectorySecurity);
}
You can also do this with recursion, but the above would be my preferred method as cleaning up permissions would be annoying.
OS Windows 7 SP1 x64
I set ACL permissions to my folder for some account:
var accessRule = new FileSystemAccessRule(account,
fileSystemRights: FileSystemRights.Modify,
inheritanceFlags: InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
propagationFlags: PropagationFlags.None,
type: AccessControlType.Allow);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = directoryinfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(accessRule);
// Set the new access settings.
directoryinfo.SetAccessControl(dSecurity);
At this case I allowed read and write for account. It works fine.
But later I wanted to change the rights for that account: to allow read only permissions. I use such code:
var accessRule = new FileSystemAccessRule(account,
fileSystemRights: FileSystemRights.ReadAndExecute,
inheritanceFlags: InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
propagationFlags: PropagationFlags.None,
type: AccessControlType.Allow);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = directoryinfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(accessRule);
// Set the new access settings.
directoryinfo.SetAccessControl(dSecurity);
But the account has write permissions still. How can I fix it? Also, how can I remove the ACL permissions for that account when I will want to do it later?
It is quite easy:
dSecurity = directoryinfo.GetAccessControl();
accessRule = new FileSystemAccessRule(account,
fileSystemRights: FileSystemRights.ReadAndExecute,
inheritanceFlags: InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
propagationFlags: PropagationFlags.None,
type: AccessControlType.Allow);
dSecurity.SetAccessRule(accessRule);
directoryinfo.SetAccessControl(dSecurity);
and for removing:
dSecurity = directoryinfo.GetAccessControl();
accessRule = new FileSystemAccessRule(account, 0, 0);
dSecurity.RemoveAccessRuleAll(accessRule);
directoryinfo.SetAccessControl(dSecurity);
Note that the SetAccessRule will work even if there is no access rule for the account (so it can even be used to do the initial Add)
Why do the following access rule show up as "Special permission" when I browse permissions in the explorer property window? I want it to appear as a normal "modify" access.
var di = new DirectoryInfo(ConfigDirectory);
DirectorySecurity security = di.GetAccessControl();
var rule = new FileSystemAccessRule(domainSid, FileSystemRights.Modify, AccessControlType.Allow);
security.AddAccessRule(rule);
di.SetAccessControl(security);
domainSid = SID for domain users.
How do I create the rule so it's inherited by all files that are created in that folder?
Use this instead:
var di = new DirectoryInfo(ConfigDirectory);
DirectorySecurity security = di.GetAccessControl();
var rule = new FileSystemAccessRule(domainSid, FileSystemRights.Modify, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow);
security.AddAccessRule(rule);
security.SetAccessRule(rule);
di.SetAccessControl(security);
The difference is using a FileSystemAccessRule Constructor that allows you to specifiy inheritance and the call to security.SetAccessRule(rule);