C # Проверка, имеет ли пользователь право на запись в папку - PullRequest
169 голосов
/ 11 сентября 2009

Мне нужно проверить, может ли пользователь записать в папку, прежде чем пытаться это сделать.

Я реализовал следующий метод (в C # 2.0), который пытается получить разрешения безопасности для папки, используя 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;
    }
}

Когда я гуглял, как проверить доступ на запись, ничего подобного не возникало, и было очень сложно на самом деле проверить разрешения в Windows. Я обеспокоен тем, что я чрезмерно упрощаю вещи и что этот метод не является надежным, хотя, похоже, он работает.

Будет ли мой метод проверки правильности работы текущего пользователя с правами на запись?

Ответы [ 18 ]

3 голосов
/ 26 ноября 2009

Вы можете попробовать следующий блок кода, чтобы проверить, имеет ли каталог доступ для записи. Проверяет 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 
}
2 голосов
/ 09 октября 2009

http://www.codeproject.com/KB/files/UserFileAccessRights.aspx

Очень полезный класс, проверьте улучшенную версию в сообщениях ниже.

2 голосов
/ 11 сентября 2009

У вас есть потенциальное состояние гонки в вашем коде - что произойдет, если у пользователя будут права на запись в папку при проверке, но до того, как пользователь действительно запишет в папку, это разрешение будет снято? При записи выдается исключение, которое вам нужно будет отловить и обработать. Так что первоначальная проверка бессмысленна. Вы также можете просто написать и обработать любые исключения. Это стандартный шаблон для вашей ситуации.

2 голосов
/ 25 января 2018

Вышеуказанные решения хороши, но для меня этот код прост и выполним. Просто создайте временный файл. Если файл создан, его средний пользователь имеет право на запись.

        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;
        }
1 голос
/ 17 июня 2011

Простая попытка доступа к рассматриваемому файлу не обязательно достаточна. Тест будет выполняться с разрешениями пользователя, запустившего программу. Это не обязательно те права пользователя, с которыми вы хотите проверить.

0 голосов
/ 11 сентября 2009

Я согласен с Эшем, это должно быть хорошо. В качестве альтернативы вы могли бы использовать декларативный CAS и фактически запретить запуск программы, если у них нет доступа.

Я полагаю, что некоторые функции CAS могут отсутствовать в C # 4.0 из того, что я слышал, не уверен, может ли это быть проблемой или нет.

0 голосов
/ 08 января 2016

Я столкнулся с той же проблемой: как проверить, могу ли я читать / писать в определенном каталоге. Я получил простое решение ... на самом деле проверить его. Вот мое простое, но эффективное решение.

 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

}

Надеюсь, это поможет!

0 голосов
/ 08 января 2014

Мне не удалось заставить GetAccessControl () выдать исключение в Windows 7, как рекомендовано в принятом ответе.

Я использовал вариант sdds's answer:

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

Надеюсь, это поможет.

...