c# permissions folder

C#Prueba si el usuario tiene acceso de escritura a una carpeta



permissions folder (18)

Aprecio que este sea un poco tarde para esta publicación, pero es posible que este código sea útil.

string path = @"c:/temp"; string NtAccountName = @"MyDomain/MyUserOrGroup"; DirectoryInfo di = new DirectoryInfo(path); DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All); AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount)); //Go through the rules returned from the DirectorySecurity foreach (AuthorizationRule rule in rules) { //If we find one that matches the identity we are looking for if (rule.IdentityReference.Value.Equals(NtAccountName,StringComparison.CurrentCultureIgnoreCase)) { var filesystemAccessRule = (FileSystemAccessRule)rule; //Cast to a FileSystemAccessRule to check for access rights if ((filesystemAccessRule.FileSystemRights & FileSystemRights.WriteData)>0 && filesystemAccessRule.AccessControlType != AccessControlType.Deny) { Console.WriteLine(string.Format("{0} has write access to {1}", NtAccountName, path)); } else { Console.WriteLine(string.Format("{0} does not have write access to {1}", NtAccountName, path)); } } } Console.ReadLine();

Suelta eso en una aplicación de consola y mira si hace lo que necesitas.

Necesito probar si un usuario puede escribir en una carpeta antes de intentar hacerlo.

Implementé el siguiente método (en C # 2.0) que intenta recuperar los permisos de seguridad para la carpeta utilizando el método Directory.GetAccessControl() .

private bool hasWriteAccessToFolder(string folderPath) { try { // Attempt to get a list of security permissions from the folder. // This will raise an exception if the path is read only or do not have access to view the permissions. System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath); return true; } catch (UnauthorizedAccessException) { return false; } }

Cuando busqué en google cómo probar el acceso de escritura, no apareció nada como esto y me pareció muy complicado probar los permisos en Windows. Me preocupa que estoy simplificando demasiado las cosas y que este método no es sólido, aunque parece funcionar.

¿Mi método para probar si el usuario actual tiene acceso de escritura funciona correctamente?


Aquí hay una versión modificada de la respuesta de CsabaS , que da cuenta de las reglas explícitas de denegación de acceso. La función pasa por todas las FileSystemAccessRules para un directorio y comprueba si el usuario actual tiene un rol que tiene acceso a un directorio. Si no se encuentran tales roles o el usuario tiene un rol con acceso denegado, la función devuelve falso. Para verificar los derechos de lectura, pase FileSystemRights. Lea la función; para derechos de escritura, pase FileSystemRights.Write. Si desea verificar los derechos de un usuario arbitrario y no los actuales, sustituya el usuario actual WindowsIdentity por el WindowsIdentity deseado. También desaconsejaría confiar en funciones como esta para determinar si el usuario puede usar el directorio de manera segura. This respuesta explica perfectamente por qué.

public static bool UserHasDirectoryAccessRights(string path, FileSystemRights accessRights) { var isInRoleWithAccess = false; try { var di = new DirectoryInfo(path); var acl = di.GetAccessControl(); var rules = acl.GetAccessRules(true, true, typeof(NTAccount)); var currentUser = WindowsIdentity.GetCurrent(); var principal = new WindowsPrincipal(currentUser); foreach (AuthorizationRule rule in rules) { var fsAccessRule = rule as FileSystemAccessRule; if (fsAccessRule == null) continue; if ((fsAccessRule.FileSystemRights & accessRights) > 0) { var ntAccount = rule.IdentityReference as NTAccount; if (ntAccount == null) continue; if (principal.IsInRole(ntAccount.Value)) { if (fsAccessRule.AccessControlType == AccessControlType.Deny) return false; isInRoleWithAccess = true; } } } } catch (UnauthorizedAccessException) { return false; } return isInRoleWithAccess; }


En mi humilde opinión, la única forma 100% confiable de probar si puede escribir en un directorio es escribirle y eventualmente atrapar excepciones.


Esa es una forma perfectamente válida de verificar el acceso a la carpeta en C #. El único lugar donde podría caerse es si necesita llamar esto en un círculo cerrado donde la sobrecarga de una excepción puede ser un problema.

Se han realizado otras questions similar anteriormente.


Estoy de acuerdo con Ash, eso debería estar bien. Alternativamente, podría utilizar CAS declarativo y, de hecho, evitar que el programa se ejecute en primer lugar si no tienen acceso.

Creo que algunas de las características CAS pueden no estar presentes en C # 4.0 por lo que he escuchado, no estoy seguro si eso podría ser un problema o no.


Intenté la mayoría de estos, pero dan falsos positivos, todos por el mismo motivo. No es suficiente probar el directorio para obtener un permiso disponible, debes verificar que el usuario que ha iniciado sesión sea miembro de un grupo que tenga ese permiso. permiso. Para hacer esto obtienes la identidad de los usuarios y verifica si es un miembro de un grupo que contiene la FileSystemAccessRule IdentityReference. Lo he probado, funciona sin problemas ...

/// <summary> /// Test a directory for create file access permissions /// </summary> /// <param name="DirectoryPath">Full path to directory </param> /// <param name="AccessRight">File System right tested</param> /// <returns>State [bool]</returns> public static bool DirectoryHasPermission(string DirectoryPath, FileSystemRights AccessRight) { if (string.IsNullOrEmpty(DirectoryPath)) return false; try { AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); WindowsIdentity identity = WindowsIdentity.GetCurrent(); foreach (FileSystemAccessRule rule in rules) { if (identity.Groups.Contains(rule.IdentityReference)) { if ((AccessRight & rule.FileSystemRights) == AccessRight) { if (rule.AccessControlType == AccessControlType.Allow) return true; } } } } catch { } return false; }


Las soluciones anteriores son buenas, pero para mí, creo que este código es simple y viable. Solo crea un archivo temporal. Si se crea el archivo, su usuario medio tiene acceso de escritura.

public static bool HasWritePermission(string tempfilepath) { try { System.IO.File.Create(tempfilepath + "temp.txt").Close(); System.IO.File.Delete(tempfilepath + "temp.txt"); } catch (System.UnauthorizedAccessException ex) { return false; } return true; }


Me enfrenté al mismo problema: cómo verificar si puedo leer / escribir en un directorio en particular. Terminé con la solución fácil para ... realmente probarlo. Aquí está mi solución simple aunque efectiva.

class Program { /// <summary> /// Tests if can read files and if any are present /// </summary> /// <param name="dirPath"></param> /// <returns></returns> private genericResponse check_canRead(string dirPath) { try { IEnumerable<string> files = Directory.EnumerateFiles(dirPath); if (files.Count().Equals(0)) return new genericResponse() { status = true, idMsg = genericResponseType.NothingToRead }; return new genericResponse() { status = true, idMsg = genericResponseType.OK }; } catch (DirectoryNotFoundException ex) { return new genericResponse() { status = false, idMsg = genericResponseType.ItemNotFound }; } catch (UnauthorizedAccessException ex) { return new genericResponse() { status = false, idMsg = genericResponseType.CannotRead }; } } /// <summary> /// Tests if can wirte both files or Directory /// </summary> /// <param name="dirPath"></param> /// <returns></returns> private genericResponse check_canWrite(string dirPath) { try { string testDir = "__TESTDIR__"; Directory.CreateDirectory(string.Join("/", dirPath, testDir)); Directory.Delete(string.Join("/", dirPath, testDir)); string testFile = "__TESTFILE__.txt"; try { TextWriter tw = new StreamWriter(string.Join("/", dirPath, testFile), false); tw.WriteLine(testFile); tw.Close(); File.Delete(string.Join("/", dirPath, testFile)); return new genericResponse() { status = true, idMsg = genericResponseType.OK }; } catch (UnauthorizedAccessException ex) { return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteFile }; } } catch (UnauthorizedAccessException ex) { return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteDir }; } } } public class genericResponse { public bool status { get; set; } public genericResponseType idMsg { get; set; } public string msg { get; set; } } public enum genericResponseType { NothingToRead = 1, OK = 0, CannotRead = -1, CannotWriteDir = -2, CannotWriteFile = -3, ItemNotFound = -4 }

Espero eso ayude !


No pude obtener GetAccessControl () para lanzar una excepción en Windows 7 como se recomienda en la respuesta aceptada.

Terminé usando una variación de respuesta de :

try { bool writeable = false; WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); DirectorySecurity security = Directory.GetAccessControl(pstrPath); AuthorizationRuleCollection authRules = security.GetAccessRules(true, true, typeof(SecurityIdentifier)); foreach (FileSystemAccessRule accessRule in authRules) { if (principal.IsInRole(accessRule.IdentityReference as SecurityIdentifier)) { if ((FileSystemRights.WriteData & accessRule.FileSystemRights) == FileSystemRights.WriteData) { if (accessRule.AccessControlType == AccessControlType.Allow) { writeable = true; } else if (accessRule.AccessControlType == AccessControlType.Deny) { //Deny usually overrides any Allow return false; } } } } return writeable; } catch (UnauthorizedAccessException) { return false; }

Espero que esto ayude.


Por ejemplo, para todos los usuarios (Builtin / Users), este método funciona bien, disfruta.

public static bool HasFolderWritePermission(string destDir) { if(string.IsNullOrEmpty(destDir) || !Directory.Exists(destDir)) return false; try { DirectorySecurity security = Directory.GetAccessControl(destDir); SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); foreach(AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier))) { if(rule.IdentityReference == users) { FileSystemAccessRule rights = ((FileSystemAccessRule)rule); if(rights.AccessControlType == AccessControlType.Allow) { if(rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true; } } } return false; } catch { return false; } }


Prueba esto:

try { DirectoryInfo di = new DirectoryInfo(path); DirectorySecurity acl = di.GetAccessControl(); AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount)); WindowsIdentity currentUser = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(currentUser); foreach (AuthorizationRule rule in rules) { FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule; if (fsAccessRule == null) continue; if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0) { NTAccount ntAccount = rule.IdentityReference as NTAccount; if (ntAccount == null) { continue; } if (principal.IsInRole(ntAccount.Value)) { Console.WriteLine("Current user is in role of {0}, has write access", ntAccount.Value); continue; } Console.WriteLine("Current user is not in role of {0}, does not have write access", ntAccount.Value); } } } catch (UnauthorizedAccessException) { Console.WriteLine("does not have write access"); }


Puede intentar seguir el bloque de código para verificar si el directorio tiene acceso de escritura. Comprueba FileSystemAccessRule.

string directoryPath = "C://XYZ"; //folderBrowserDialog.SelectedPath; bool isWriteAccess = false; try { AuthorizationRuleCollection collection = Directory.GetAccessControl(directoryPath) .GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)); foreach (FileSystemAccessRule rule in collection) { if (rule.AccessControlType == AccessControlType.Allow) { isWriteAccess = true; break; } } } catch (UnauthorizedAccessException ex) { isWriteAccess = false; } catch (Exception ex) { isWriteAccess = false; } if (!isWriteAccess) { //handle notifications }


Simplemente intentar acceder al archivo en cuestión no es necesariamente suficiente. La prueba se ejecutará con los permisos del usuario que ejecuta el programa, que no es necesariamente el permiso del usuario que desea probar.


Su código obtiene DirectorySecurity para un directorio determinado y maneja una excepción (debido a que no tiene acceso a la información de seguridad) correctamente. Sin embargo, en su muestra, en realidad no interroga al objeto devuelto para ver qué acceso está permitido, y creo que debe agregarlo.


Usé la misma función para verificar si el archivo tieneWriteAccess:

private static bool HasWriteAccessToFile(string filePath) { try { // Attempt to get a list of security permissions from the file. // This will raise an exception if the path is read only or do not have access to view the permissions. File.GetAccessControl(filePath); return true; } catch (UnauthorizedAccessException) { return false; } }


Usted tiene una posible condición de carrera en su código: ¿qué sucede si el usuario tiene permisos para escribir en la carpeta cuando marca, pero antes de que el usuario realmente escriba en la carpeta este permiso se retire? La escritura arrojará una excepción que necesitará capturar y manejar. Entonces la verificación inicial no tiene sentido. Es mejor que simplemente escribas y manejes cualquier excepción. Este es el patrón estándar para su situación.



public bool IsDirectoryWritable(string dirPath, bool throwIfFails = false) { try { using (FileStream fs = File.Create( Path.Combine( dirPath, Path.GetRandomFileName() ), 1, FileOptions.DeleteOnClose) ) { } return true; } catch { if (throwIfFails) throw; else return false; } }