Морал исключений, связанных с открытием FileStream - PullRequest
13 голосов
/ 21 февраля 2012

Хорошо, поэтому я искал ответ на этот вопрос во многих местах, но я открыт для любых ссылок, если пропустил что-то очевидное.

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

  • Файл был заблокирован другим процессом, так что этот процесс не может записать в него.
  • У пользователя нет соответствующих прав доступадля записи в файл (как, например, их пользовательские разрешения, как видно на экране «Свойства» для файла в проводнике Windows, не дают пользователю права на запись)
  • Файл требует «повышенных» разрешений для доступа кфайл.

Я использую объект FileStream.Я просмотрел документацию msdn для создания экземпляра FileStream , и мне совершенно не ясно, что делает Исключение для чего выше, и как их различать.Я признаю, что мой опыт работы с Windows ограничен, поэтому я могу упустить что-то очевидное.Мои извинения, если так.

1 Ответ

5 голосов
/ 21 февраля 2012

Вот что вы можете сделать:

1) Вы можете проверить, есть ли у вас права доступа к файлу до , пытаясь получить доступ к вашему файлу.Из этого SO потока , вот метод, который должен возвращать true, если у пользователя есть права Write (т.е. при щелчке правой кнопкой мыши по файлу -> свойство -> безопасность).Это относится к вашей точке (2) для непривилегированных прав доступа (обратите внимание, что, возможно, есть что-то более надежное / защищенное от ошибок, чтобы получить эту информацию, чем код ниже):

public static bool HasWritePermissionOnFile(string path)
{
    bool writeAllow = false;
    bool writeDeny = false;

    FileSecurity accessControlList = File.GetAccessControl(path);
    if (accessControlList == null)
    {
        return false;
    }

    var accessRules = accessControlList.GetAccessRules(true, true, typeof(SecurityIdentifier));
    if (accessRules == null)
    {
        return false;
    }

    foreach (FileSystemAccessRule rule in accessRules)
    {
        if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write)
        {
            continue;
        }

        if (rule.AccessControlType == AccessControlType.Allow)
        {
            writeAllow = true;
        }
        else if (rule.AccessControlType == AccessControlType.Deny)
        {
            writeDeny = true;
        }
    }

    return writeAllow && !writeDeny;
}

2) Попробуйте создать экземплярваш FileStream и ловите исключения:

try
{
    string file = "...";
    bool hasWritePermission = HasWritePermissionOnFile(file);
    using (FileStream fs = new FileStream(file, FileMode.Open))
    {
    }
}
catch (UnauthorizedAccessException ex)
{
    // Insert some logic here
}
catch (FileNotFoundException ex)
{
    // Insert some logic here
}
catch (IOException ex)
{
    // Insert some logic here
}

В вашем случае (3) (для файла требуется повышение прав), UnauthorizedAccessException выбрасывается.

В вашем случае (1) (файлзаблокирован другим процессом), IOException выбрасывается.Затем вы можете проверить HRESULT исключения для получения более подробной информации:

catch (IOException ex)
{
    // Gets the HRESULT
    int hresult = Marshal.GetHRForException(ex);

    // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
    // for system error code
    switch (hresult & 0x0000FFFF)
    {
        case 32:    //ERROR_SHARING_VIOLATION
            Console.WriteLine("File is in use by another process");
            break;
    }
}

Теперь вы сможете различить 3 варианта использования.

...