C#检查文件是否已打开

3

我需要验证特定文件是否打开,以防止复制该文件。

我尝试了很多示例,但都没有成功!例如,我尝试了这个:

protected virtual bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;

    try
    {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
        //the file is unavailable because it is:
        //still being written to
        //or being processed by another thread
        //or does not exist (has already been processed)
        return true;
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }

    //file is not locked
    return false;
}

我需要指导...我哪里做错了?有什么建议吗?

1
这是一个经典的问题,你要么在全局声明stream变量,要么在代码中的其他地方声明,但没有将原始创建的new实例包装在using(){}子句中。搜索所有使用stream的地方,并确保你Dispose()、Close()、Flush()和Close流,也可能是file.Open()方法需要是FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - MethodMan
为什么你需要验证特定文件是否已打开以防止复制该文件,而不是尝试复制文件并捕获任何异常? - Austin Salonen
1
@DJKRAZE:提供的代码有效地实现了using (var stream = file.Open(...)) { ... } - Austin Salonen
你是想创建一个锁,还是想查看锁是否存在? - Joel Coehoorn
相关链接:https://dev59.com/2HVC5IYBdhLWcg3whRgw#265958 - Joel Coehoorn
我的目标是自动复制一个文件,但如果该文件正在使用中,我希望阻止此复制... - user1921145
2个回答

2
如果您想知道您的应用程序是否已经打开文件,您应该将FileStream保存在字段中,并在关闭流时将字段重置为null。然后,您只需测试并获取文件的FileStream即可。
如果您想知道另一个应用程序是否已经打开文件,那么您无法做太多事情。当您尝试打开文件时,可能会出现异常。但是,即使您知道,您也无法防止复制该文件,因为您的应用程序中没有对该文件或其FileStream的引用。

我认为他可能想要自己复制文件,并且希望在复制之前检查每个文件是否已打开。 - Matthew Watson
我的目标是自动复制一个文件,但如果该文件正在使用中,我希望阻止此复制... - user1921145

2

在这种情况下,您可能会遭受线程竞争条件的影响,有记录的例子表明这被用作安全漏洞。如果您检查文件是否可用,但尝试使用它时出现错误,那么恶意用户可以利用此点来强制执行并利用您的代码。

最好的方法是使用try catch/finally尝试获取文件句柄。

try
{
   using (Stream stream = new FileStream("MyFilename.txt", FileMode.Open))
   {
        // File/Stream manipulating code here
   }
} catch {
  //check here why it failed and ask user to retry if the file is in use.
}

或者

看看这些其他选项

https://dev59.com/XnNA5IYBdhLWcg3wpvtg#11060322


在你的示例中(https://dev59.com/XnNA5IYBdhLWcg3wpvtg#11060322),你有“int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);”请解释一下,因为C#不知道Marshal是什么,即使我在文档顶部放置了“using System.Runtime.InteropServices.Marshal;”。 - user1921145

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接