与打开FileStream相关的异常错误

时间:2012-02-21 00:33:37

标签: c# exception-handling filestream

好的,所以我在很多地方搜索过这个问题的答案,但如果我错过了一些明显的东西,我会对任何链接持开放态度。

我有兴趣在用户尝试打开特定文件时向用户生成合理的错误消息,但无论出于何种原因,程序都无法访问该文件。我想区分下列情况:

  • 该文件被另一个进程锁定,导致此进程无法写入该文件。
  • 用户没有相应的访问权限来写入文件(例如,他们的用户权限,如Windows资源管理器中的文件的“属性”屏幕中所示,不授予用户写入权限)
  • 该文件需要“提升”权限才能访问该文件。

我正在使用FileStream对象。我查看了msdn documentation for instantiating a FileStream,对于我来说,哪个Exception为上述内容做了什么以及如何区分它们并不是很清楚。我承认我在Windows编程方面的经验有限,所以我可能会遗漏一些明显的东西。如果是的话我很抱歉。

1 个答案:

答案 0 :(得分:5)

以下是您可以做的事情:

1)您可以测试您是否有权访问之前尝试访问您的文件的文件。从this SO thread开始,如果用户具有Write权限(即右键单击文件时,>属性 - >安全性),则此方法应返回true。这涵盖了您对未授权访问权限的观点(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个用例。