C# 与打开文件流相关的大量异常

C# 与打开文件流相关的大量异常,c#,exception-handling,filestream,C#,Exception Handling,Filestream,好的,我已经在很多地方搜索了这个问题的答案,但是如果我错过了一些明显的东西,我愿意接受任何链接 我感兴趣的是,当用户试图打开一个特定的文件时,我会向他们发出合理的错误消息,但无论出于何种原因,程序都无法访问该文件。我想区分以下情况: 该文件已被另一个进程锁定,因此该进程无法写入该文件 用户没有写入文件的适当访问权限(如中所示,其用户权限(如Windows资源管理器中文件的“属性”屏幕中所示)不授予用户写入权限) 该文件需要“提升”权限才能访问该文件 我正在使用FileStream对象。我已经

好的,我已经在很多地方搜索了这个问题的答案,但是如果我错过了一些明显的东西,我愿意接受任何链接

我感兴趣的是,当用户试图打开一个特定的文件时,我会向他们发出合理的错误消息,但无论出于何种原因,程序都无法访问该文件。我想区分以下情况:

  • 该文件已被另一个进程锁定,因此该进程无法写入该文件
  • 用户没有写入文件的适当访问权限(如中所示,其用户权限(如Windows资源管理器中文件的“属性”屏幕中所示)不授予用户写入权限)
  • 该文件需要“提升”权限才能访问该文件

我正在使用FileStream对象。我已经看过了,但我一点也不清楚哪个异常对上述内容有什么作用,以及如何区分它们。我承认我在Windows编程方面的经验是有限的,所以我可能遗漏了一些明显的东西。如果是这样,我深表歉意。

以下是您可以做的:

1) 在尝试访问文件之前,您可以测试自己是否有权访问该文件。从中,如果用户拥有
Write
权限(即右键单击文件->属性->安全性),则此方法应返回true。这涵盖了您对未分配的访问权限的第(2)点(请注意,与下面的代码相比,获取此信息可能有更可靠/更可靠的方法):

2) 请尝试实例化您的
文件流
,并捕获异常:

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

您要检查的最后两个用例之间是否有差异?我可以想象(尽管尚未证明)他们都会抛出一个
SecurityException
,其中第一个案例会抛出一个
IOException
@M.Babcock:在某些方面,后两个案例并没有太大的不同。但是,用户(通常)必须做非常不同的事情才能访问该文件。对于第二种情况,他们可能需要请求其他用户授予他们权限。对于第三种情况,他们需要“以管理员身份运行”,或者可能将文件移出“Program Files”目录(尽管我不知道为什么它会在那里)。我想帮助用户知道他们需要做什么才能访问该文件。在我之前的评论中,我可能再次表明我对Windows操作系统的无知-如果我的解释不正确,我愿意更正。这是有意义的。听起来,通过一系列测试和检查抛出的异常,应该可以发现您正在寻找的内容。凭直觉,您可能可以使用
SecurityException
的属性来确定根本原因。这是有道理的——我将对此进行测试。尽管我不认为我能够完全信任您在这里指定的解决方案1,因为可能存在种族条件。也就是说,a)我的进程检查它是否可以访问该文件,b)其他进程打开该文件(或更改权限等),c)我的进程尝试打开该文件并失败/变得古怪/等等。实际上,可能只有情况(2)(未分配的访问权限)才存在竞争条件如果用户在
hasWritePermissionFile
检查和
新文件流
调用之间失去了权限。如果发生这种情况,将抛出一个
UnauthorizedAccessException
异常,因此您仍然能够知道“存在访问问题”。然后,您可以在
catch(UnauthorizedAccessException)
块中调用
hasWritePermissionFile
,以确保在由于高程问题引发异常时引发异常。哈,这感觉就像将竞态条件移动到UnauthorizedAccessException的catch块中一样。虽然我不确定是否有可能避免这种情况。还是有?它在正常条件下肯定能工作。谢谢出于好奇,是什么原因导致尝试实例化文件流时抛出SecurityException?@skybluecodeflier True。嗯,如果某个进程不断更改文件的安全属性,那么很难准确地知道引发
UnauthorizedAccessException
异常的原因;)事实上,在我看来,这不是一个常见的用例。
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;
    }
}