AccessReaderWriter
In Windows XP explorer you could select a group of files and change the security permissions as a batch. You can't do that in Windows 7 (without dropping down to command line), so I threw this together, put an ugly windows forms UI on it and use it all the time.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
namespace FilePermissions
{
class AccessReaderWriter
{
private readonly FileSystemRights _fileSystemRights;
private readonly string _userName;
private readonly DirectoryInfo _directory;
private FileSystemAccessRule _accessRule;
private bool _reading;
public AccessReaderWriter(string userName, string path, FileSystemRights fileSystemRights)
{
_userName = userName;
_fileSystemRights = fileSystemRights;
_directory = new DirectoryInfo(path);
}
public event EventHandler<GenericEventArgs<string>> Message;
public bool Reverse { get; set; }
public void Read()
{
_reading = true;
Execute();
}
public void Write()
{
_reading = false;
Execute();
}
public static FileSystemRights FileSystemRights(string s)
{
return (FileSystemRights)Enum.Parse(typeof(FileSystemRights), s);
}
#region processing
private void Execute()
{
if (!_directory.Exists)
{
return;
}
PrepareRun();
RecurseFileSystem(_directory);
}
private void PrepareRun()
{
//initialize fields
_accessRule = new FileSystemAccessRule(
_userName,
_fileSystemRights,
AccessControlType.Allow);
}
private bool HasUserAccess(FileSecurity acl)
{
var rules = acl.GetAccessRules(true, true, typeof(SecurityIdentifier));
var rulesForUser = from rule in rules.OfType<FileSystemAccessRule>()
where rule.AccessControlType == AccessControlType.Allow
&& rule.IdentityReference.Value
.Equals(_userName, StringComparison.OrdinalIgnoreCase)
select rule;
return (rulesForUser.Any(rule => HasFlag(rule.FileSystemRights, _fileSystemRights)));
}
private static bool HasFlag(FileSystemRights rights, FileSystemRights flag)
{
return (flag & rights) == flag;
}
private void RecurseFileSystem(DirectoryInfo di)
{
var files = di.GetFiles();
foreach (var file in files)
{
ReadFile(file);
}
IEnumerable<DirectoryInfo> dirs = di.GetDirectories();
if (Reverse)
{
dirs = dirs.Reverse();
}
foreach (var dir in dirs)
{
RecurseFileSystem(dir);
}
}
private void ReadFile(FileInfo file)
{
FileSecurity acl;
try
{
acl = file.GetAccessControl();
}
catch (UnauthorizedAccessException ex)
{
ShowStatus(file.FullName + "\n" + ex.Message);
return;
}
if (_reading)
{
if (!HasUserAccess(acl))
ShowStatus(file.FullName + " inaccessible");
return;
}
acl.SetAccessRule(_accessRule);
ShowStatus(file.FullName);
try
{
file.SetAccessControl(acl);
}
catch (IOException ex)
{
ShowStatus(ex.Message);
}
catch (UnauthorizedAccessException ex)
{
ShowStatus(ex.Message);
}
}
private void ShowStatus(string text)
{
var handler = Message;
if (handler != null)
{
var e = new GenericEventArgs<string>(text);
handler(this, e);
}
}
#endregion
}
}