区分“正在使用的文件”和.NET中的其他异常

时间:2014-10-08 15:44:43

标签: .net exception file-io directory

我正在从目录中读取文件。我需要处理我的应用程序尝试拾取仍由另一个进程写入的文件的情况,我无法控制。

我假设通过尝试打开仍然被其他东西写入的文件,我将得到一个例外。现在,我需要弄清楚文件是否有问题,在这种情况下我将它移动到另一个目录或第二个进程是否仍在写入文件,在这种情况下我想再次尝试在第二次迭代阅读目录。

任何人都知道如何区分这两个例外吗?

2 个答案:

答案 0 :(得分:4)

您可以使用Marshal.GetHRForException()方法来恢复导致引发IOException的原始Windows错误。一个例子:

static FileStream TryOpen(string path, int maxAttempts = 10, int interval = 1000) {
    for (int attempt = 0; ; attempt++) {
        try {
            return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
        }
        catch (IOException ex) {
            var err = System.Runtime.InteropServices.Marshal.GetHRForException(ex) & 0xffff;
            if (attempt < maxAttempts && err != 32) throw;
        }
        System.Threading.Thread.Sleep(interval);
    }
}

答案 1 :(得分:0)

更新:请参阅Hans Passant的答案,了解实际的解决方案。将Handle工具作为参考,因为它有助于类似的情况。

有关检查文件是否由特定流程打开的强大方法,您可以使用Handle。它是一个命令行工具,但您可以根据自己的情况使用它。

旧答案

一个 hacky 解决方案可能是简单检查异常消息。 如果包含

  另一个进程正在使用

然后你的文件被另一个进程锁定(不能告诉异常是哪一个)。 否则,它会出现其他一些I / O错误。

不幸的是,文档似乎没有说明是否仅在句柄违规时抛出IOException(否则您将能够区分抛出的异常是IOException还是衍生类似FileNotFoundException)。

示例代码:

catch (IOException ex)
{
    if (ex.Message.Contains("is being used by another process"))
    {
        // Retry logic goes here
    }
    else
    {
        // Other type of error (possibly derivative of IOException)
        throw;
    }
}

它远非完美,但系统信息可能不会发生太大变化。