与打开FileStream相关的异常错误

sky*_*ier 13 c# exception-handling filestream

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

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

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

我正在使用FileStream对象.我已经查看了用于实例化FileStreammsdn文档,并且我完全不清楚Exception是否为上述内容做了什么,以及如何区分它们.我承认我在Windows编程方面的经验有限,所以我可能会遗漏一些明显的东西.如果是这样,我道歉.

ken*_*n2k 5

这是你可以做的:

1)您可以尝试访问文件之前测试您是否有权访问该文件.从这个SO线程,这里有一个方法,如果用户有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;
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

在你的情况下(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您应该能够区分您的3个用例.