Установить права доступа к файлам для c:\program files\company\app\file для всех пользователей
У меня есть специальная программа установки, которая работала нормально, но каждый раз, когда обновляет приложение, она запрашивает разрешение администратора. Я создаю службу Windows, которая пропускает эту часть, но служба Windows дает только разрешения на доступ к файлу Системным и Администраторам, а пользователь не может выполнять новые обновления.
Чтобы исправить это, я пытаюсь (после того, как файл загружается / устанавливается в правильное место (из службы Windows, он имеет учетную запись ServiceAccount.LocalSystem),
FileSecurity access = file.GetAccessControl();
SecurityIdentifier everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
access.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.ReadAndExecute, AccessControlType.Allow));
но настройка не вступает в силу. Что мне делать отсюда?
2 ответа
Я понял. Мне просто нужно было позвонить,
file.SetAccessControl(access);
после вышесказанного. Очевидно file.GetAccessControl передает обратно копию элемента управления доступом, а не ту, которая управляет правами доступа к файлу для файла, до тех пор, пока вы не вызовите file.SetAccessControl с измененными разрешениями.
Есть еще одна оговорка, которую я обнаружил с другим файлом, который служба создавала в c:\ProgramData,
- является то, что набор должен произойти после того, как файл был записан. Применение набора к файлу заранее неэффективно.
Недавно я столкнулся с проблемой загрузки файлов из сети и хотел иметь возможность воссоздать ошибку в тесте и столкнулся с той же проблемой.
Я придумал следующий небольшой класс, чтобы помочь с этим, поскольку API для этого довольно ужасен и полон маленьких подводных камней:
public class PermissionController
{
private readonly string _file;
private readonly FileSecurity _accessControl;
private readonly SecurityIdentifier _id;
private readonly List<FileSystemAccessRule> _permissionsDenied;
public PermissionController(string file)
{
_file = file;
_accessControl = File.GetAccessControl(_file);
_id = WindowsIdentity.GetCurrent().Owner;
_permissionsDenied = new List<FileSystemAccessRule>();
}
public void Allow(params FileSystemRights[] rights)
{
foreach (var right in rights)
AddRule(Rule(right, AccessControlType.Allow));
}
public void Deny(params FileSystemRights[] rights)
{
foreach (var right in rights)
{
var rule = Rule(right, AccessControlType.Deny);
AddRule(rule);
_permissionsDenied.Add(rule);
}
}
private void AddRule(FileSystemAccessRule rule)
{
_accessControl.AddAccessRule(rule);
}
private FileSystemAccessRule Rule(FileSystemRights right, AccessControlType type)
{
return new FileSystemAccessRule(_id, right, type);
}
public void RemoveDeniedPermissions()
{
foreach (var rule in _permissionsDenied)
_accessControl.RemoveAccessRule(rule);
Apply();
}
public void Apply()
{
File.SetAccessControl(_file,_accessControl);
}
}
Код вызова выглядит так:
_permissionController = new PermissionController(_file);
_permissionController.Allow(FileSystemRights.Read, FileSystemRights.Write);
_permissionController.Deny(FileSystemRights.FullControl,
FileSystemRights.Modify,
FileSystemRights.ReadAndExecute);
_permissionController.Apply();
где _file - полный путь.
Вы должны быть осторожны, чтобы позвонить
File.SetAccessControl после добавления / удаления правил, так как в противном случае нет никакого эффекта.
Если я не понял API, вы должны добавить правило для разрешения, потому что перечисление FileSystemRights не использует флаги.
Вы также должны быть немного осторожны, поскольку отказ от права, которое вы отказали, не эквивалентен удалению правила, которое отрицает это право. Похоже, что лишенные права переопределяют разрешенные.
Вы можете просмотреть результаты, посмотрев на вкладку безопасности свойств файла в проводнике Windows.