【问题标题】:How to check if file opened?如何检查文件是否打开?
【发布时间】:2013-05-23 17:46:58
【问题描述】:

我编写了程序并且需要我自己的文件观察器(检查文件是否可以打开的循环)。像这样的:

while (loadedFiles.Count > 0 || isNeedReRead)
{
    Thread.Sleep(1000);
    if (isNeedReRead)
        ReadFromRegistry();

    foreach (var file in loadedFiles)
    {
        if (!IsFileLocked(file.Value))
        {
              // logic
        }
    }
}

来源:Is there a way to check if a file is in use?

这是我的解决方案:

try
{
    using (Stream stream = new FileStream(
        path, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
    {
        stream.Close();
        return false;
    }
}
catch (IOException)
{
    return true;
}

它适用于 Word、Excel。但是如果进程没有锁定文件,这种方法就没有帮助。例如,如果打开的位图文件正在更改,IsFileLocked 返回 false。

有什么想法吗?

【问题讨论】:

  • 如果文件更改可以接受,是否会收到通知?如果是这样,您可以使用 System.IO.FileSystemWatcher 类。
  • 这有什么用?即使您检查文件是否可以打开,也不能保证在您实际尝试打开它时仍然可以打开它,即使它是下一行代码。您仍然需要将文件访问权限封装在 try-catch 中。
  • 我无法使用 FileSystemWatcher。它在文件更改时通知。我需要 OnClosed 通知。我的程序包含一些文件。当我打开其中一些时,我的观察者开始运行。当文件关闭时,如果需要,观察者会更新它。但我可以在关闭文件之前关闭程序。在这种情况下,watcher 在程序加载时启动并检查所有以前打开的文件。如果此文件未打开,则它已更新。

标签: c# file file-io filelock


【解决方案1】:

您可以使用System.IO.FileSystemWatcher 设置监视文件,您应该能够使用NotifyFilter 属性(设置为LastAccessTime)来检测上次访问特定文件的时间。

void SetupWatcher()
{
    // Create a new FileSystemWatcher and set its properties.
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = @"C:\";
    /* Watch for changes in LastAccess and LastWrite times, and
       the renaming of files or directories. */
    watcher.NotifyFilter = NotifyFilters.LastAccess;

    // Only watch text files.
    watcher.Filter = "*.txt";

    // Add event handlers.
    watcher.Changed += new FileSystemEventHandler(OnChanged);
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);

        // Begin watching.
        watcher.EnableRaisingEvents = true;
}

// Define the event handlers. 
    private static void OnChanged(object source, FileSystemEventArgs e)
    {
        // Specify what is done when a file is changed, created, or deleted.
       Console.WriteLine("File: " +  e.FullPath + " " + e.ChangeType);
    }

private static void OnRenamed(object source, RenamedEventArgs e)
{
    // Specify what is done when a file is renamed.
    Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}

假设这是 windows 的另一个选项是枚举每个进程的打开文件句柄列表。 here 发布的代码有一个不错的实现,所以你所要做的就是调用

DetectOpenFiles.GetOpenFilesEnumerator(processID);

但是,如果一个进程打开一个文件,然后将其内容读入内存然后关闭该文件,您将无法使用监控选项(如上所列),因为该进程在读取文件后实际上并没有再打开该文件进入记忆。

【讨论】:

  • 我无法使用 FileSystemWatcher。请参阅问题下方的评论。
  • 但是“DetectOpenFiles.GetOpenFilesEnumerator(processID);”我喜欢。我会试试这个。
  • @Max 更新了答案,包括检测打开文件句柄列表的可能性。
猜你喜欢
  • 1970-01-01
  • 2012-08-30
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 2015-12-01
相关资源
最近更新 更多