2012-02-21 46 views
12

好吧,所以我已经在很多地方搜索了这个问题的答案,但是如果我错过了某些明显的东西,我会接受任何链接。与打开FileStream相关的例外情况恶作剧

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

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

我正在使用FileStream对象。我已经看了msdn documentation for instantiating a FileStream,而且我完全不清楚上面的Exception是什么,以及如何区分它们。我承认我在Windows编程方面的经验有限,所以我可能会漏掉一些明显的东西。如果是的话,我很抱歉。

+1

你想检查的最后2个案例有区别吗?我会想象(虽然没有证明)他们都会抛出一个'SecurityException',第一个案例会抛出一个'IOException'。 – 2012-02-21 00:49:22

+0

@ M.Babcock:在某些方面,最后两种情况并没有很大的不同。但是,用户必须(通常)为了访问文件而做了非常不同的事情。对于第二种情况,他们可能需要请求其他用户授予他们许可。对于第三种情况,他们需要“以管理员身份运行”或者将文件移出“Program Files”目录(尽管为什么它会出现在我不知道的地方)。我想帮助用户知道他们需要做什么才能访问该文件。 – skybluecodeflier 2012-02-21 00:57:37

+0

在我之前的评论中,我可能再次表现出我对Windows操作系统的无知 - 如果我的解释不正确,我愿意纠正。 – skybluecodeflier 2012-02-21 00:58:25

回答

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个用例。

+0

嗯。这是有道理的 - 我会测试这个。虽然我不认为我可以完全信任您在此处指定的解决方案1,因为可能存在竞争条件。也就是说,a)我的进程检查是否可以访问文件,b)其他进程打开文件(或更改权限等),c)我的进程尝试打开文件并失败/出现胡思乱想等。 – skybluecodeflier 2012-02-21 15:55:41

+0

实际上,如果用户在'HasWritePermissionOnFile'检查和'New FileStream'调用之间失去权限,则只有情况(2)(不适用的访问权限)才可能存在争用条件。如果发生这种情况,会抛出一个'UnauthorizedAccessException'异常,所以您仍然可以知道“存在访问问题”。然后,您可以在'catch(UnauthorizedAccessException)'块内调用'HasWritePermissionOnFile'来确保由于提升问题抛出的异常。 – ken2k 2012-02-21 16:08:24

+0

Ha,感觉就像是将竞争条件移入UnauthorizedAccessException的catch块。虽然我不确定是否有可能避免这种情况。或者在那里?它在正常情况下肯定有效。谢谢! – skybluecodeflier 2012-02-21 16:38:24