Question

I wrote program and need my own file watcher (loop that checks if file can be opened). Something like this:

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

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

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

Here is my solution:

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

It works fine with Word, Excel. But if the process does not lock the file, this method doesn't help. For example if an open bitmap file is changing, IsFileLocked returns false.

Any ideas?

Was it helpful?

Solution

You can setup monitoring the file by using the System.IO.FileSystemWatcher you should be able to use that the NotifyFilter property (set to LastAccessTime) to detect when a particular file was last accessed.

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);
}

Another option assuming this is windows is to enumerate the list of open file handles for each process. The code posted here has a decent implementation so all you have to do is call

DetectOpenFiles.GetOpenFilesEnumerator(processID);

However, if a process opens a file reads the contents into memory then closes the file, you will be stuck with the monitoring option (listed above), since the process does not actually have the file open any longer once it is read into memory.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top