217 votes

C# Tester si l'utilisateur a un accès en écriture à un dossier

Je dois tester si un utilisateur peut écrire dans un dossier avant de tenter de le faire.

J'ai implémenté la méthode suivante (en C# 2.0) qui tente de récupérer les autorisations de sécurité pour le dossier en utilisant la méthode suivante Directory.GetAccessControl() méthode.

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;
    }
}

Lorsque j'ai cherché sur Google comment tester l'accès en écriture, rien de tel n'est apparu et il semblait très compliqué de tester les permissions dans Windows. Je crains de trop simplifier les choses et que cette méthode ne soit pas robuste, même si elle semble fonctionner.

Ma méthode pour tester si l'utilisateur actuel a un accès en écriture fonctionnera-t-elle correctement ?

14 votes

C'est ne pas avoir accès à voir les permissions sont-elles vraiment les mêmes que celles qui interdisent d'y écrire ?

87voto

priit Points 109
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;
    }
}

8 votes

Cette réponse permettra d'attraper toutes les exceptions qui pourraient se produire lors de la tentative d'écriture d'un fichier, et pas seulement les violations de permission.

0 votes

Presque bon ! mais comment faire sans créer un fichier réel... et si un fichier avec le même nom existe déjà là... bel essai cependant :)

7 votes

G.Y, string tempFileName = Path.GetRandomFileName(); de toute évidence

83voto

Duncan Howe Points 1772

J'apprécie le fait que ce soit un peu tard pour ce post, mais vous pourriez trouver ce bout de code utile.

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();

Placez-la dans une application Console et voyez si elle répond à vos besoins.

0 votes

En plein dans le mille ! Cela m'aide beaucoup !

0 votes

Je reçois une exception lors de l'appel à GetAccessControl mais mon logiciel est capable d'écrire dans le répertoire que je regarde ?

0 votes

@JonCage - quelle exception obtenez-vous ? La première chose qui vous vient à l'esprit est, ironiquement, un problème de sécurité. Le compte sous lequel votre application est exécutée a-t-il la permission d'obtenir les informations ACL ?

68voto

Ash Points 31541

C'est une façon parfaitement valable de vérifier l'accès aux dossiers en C#. Le seul endroit où cela pourrait échouer est si vous devez l'appeler dans une boucle serrée où l'overhead d'une exception mai être un problème.

Il y a eu d'autres similaire questions demandé précédemment.

1 votes

Il est amusant de constater que j'avais une de ces autres questions ouverte dans un autre onglet, mais que je n'avais pas vu la réponse concernant DirectorySecurity. tous les réponses, pas seulement celle qui est acceptée;-)

0 votes

Ne tombera-t-il pas également lorsque vous utiliserez des chemins longs dans Windows ?

14 votes

Cela ne vous dira pas si vous avez le droit d'écriture, mais seulement si vous pouvez consulter les autorisations sur ce dossier ou non. Il se peut également que vous puissiez écrire mais que vous ne puissiez pas consulter les autorisations.

15voto

UGEEN Points 2243

Par exemple pour tous les utilisateurs (Builtin \Users ), cette méthode fonctionne bien - profitez-en.

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;
    }
}

15voto

Darin Dimitrov Points 528142

À mon avis, la seule façon fiable à 100 % de tester si vous pouvez écrire dans un répertoire est d'y écrire réellement et d'attraper éventuellement des exceptions.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X