Search code examples
c#ioexceptionfilesystemwatcher

Unhandled Exception: System.IO.IOException: The process cannot access the file


I am not sure how to solve this error.

Update

Zen's solution solved this error for when the LogFile\FWLog.txt file already exists, but the error still persists when the LogFile\FWLot.txt doesn't exist.

Unhandled Exception: System.IO.IOException: The process cannot access the file 'C:\Users\user\OneDrive\CodeWorkspace\NET\fw\fw\LogFile\FWLog.txt' because it is being used by another process.

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.File.InternalReadAllBytes(String path, Boolean checkHost)
at FW.CreateLog(String logName, String path, DateTime time)
at FW.Watch(String path) at FW.Run()
at FW.Main()

Code:

using System;
using System.IO;

public class FW
{
    private static StreamWriter log;
    public static void Main()
    {
        Run();
    }

    private static void Run()
    {
        string option = "";
        Console.WriteLine("File System Watcher\nThis program monitors activity in a specified directory.");
        string[] args = Environment.GetCommandLineArgs();
        if (args.Length >= 2)
        {
            String path = args[1];
            Watch(path);
        }
        while (!option.Equals("3"))
        {
            do
            {
                Console.Write("Choose an option:\n[1] Monitor a direcotry.\n[2] Open log history\n[3] Quit\n>> ");
                option = Console.ReadLine();
            } while (!option.Equals("1") && !option.Equals("2") && !option.Equals("3"));
            switch (option)
            {
                case "1":
                    Watch("");
                    break;
                case "2":
                    if ((Directory.Exists("LogFile") && !File.Exists("LogFile\\FWLog.txt")) || !Directory.Exists("LogFile"))
                    {
                        Console.WriteLine("There are no saved logs.");
                    }
                    else
                    {
                        Console.WriteLine("\nLog History");
                        DumpLog("LogFile\\FWLog.txt");
                    }
                    break;
            }
        }
        Console.WriteLine("Quiting...");
    }

    //[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    private static void Watch(string path)
    {
        DateTime time = DateTime.Now;
        string logName = "LogFile\\FWLog.txt";
        while (!Directory.Exists(path))
        {
            Console.Write("Please enter a valid absolute directory path (i.e. C:\\Users\\john\\Documents)\n>> ");
            path = Console.ReadLine();
        }
        Console.WriteLine("Monitoring: " + path);
        CreateLog(logName, path, time);
        log = File.AppendText(logName);
        // Create a new FileSystemWatcher and set its properties.
        using (FileSystemWatcher watcher = new FileSystemWatcher())
        {
            watcher.IncludeSubdirectories = true;
            watcher.Path = path;

            // Watch for changes in LastAccess and LastWrite times, and
            // the renaming of files or directories.
            watcher.NotifyFilter = NotifyFilters.LastWrite
                                 | NotifyFilters.FileName
                                 | NotifyFilters.DirectoryName;

            // Add event handlers.
            watcher.Changed += OnChanged;
            watcher.Created += OnChanged;
            watcher.Deleted += OnChanged;
            watcher.Renamed += OnRenamed;

            // Begin watching.
            watcher.EnableRaisingEvents = true;

            // Wait for the user to quit the program.
            Console.WriteLine("Press 'q' to stop monitoring.");
            while (!(Console.ReadLine()).Equals("q")) ;
        }
        log.Close();
    }
    // Define the event handlers.
    private static void OnChanged(object source, FileSystemEventArgs e)
    {
        string status = $"{Path.GetFileName(e.FullPath)} in {Path.GetDirectoryName(e.FullPath)} {e.ChangeType} {DateTime.Now}";
        // Specify what is done when a file is changed, created, or deleted.
        if ((e.FullPath).Contains("LogFile\\FWLog.txt"))
        {
            return;
        }
        else
        {
            Console.WriteLine(status);
            log.WriteLine(status);
        }
    }

    private static void OnRenamed(object source, RenamedEventArgs e)
    {
        string status = $"{Path.GetFileName(e.OldFullPath)} Renamed to {Path.GetFileName(e.FullPath)} in {Path.GetDirectoryName(e.FullPath)} {DateTime.Now}";
        // Specify what is done when a file is renamed.
        Console.WriteLine(status);
        log.WriteLine(status);
    }

    private static void CreateLog(string logName, string path, DateTime time)
    {
        if (!Directory.Exists("LogFile"))
            Directory.CreateDirectory("LogFile");
        if (!File.Exists(logName))
            File.Create(logName);
        using (StreamWriter logCreate = File.AppendText(logName))
        {
            if (File.ReadAllBytes(logName).Length == 0)
            {
                logCreate.WriteLine($"Monitored: {path} {time}");
            }
            else
            {
                logCreate.WriteLine($"\nMonitored: {path} {time}");
            }
            logCreate.Close();
        }
    }

    private static void DumpLog(string logFile)
    {
        string line;
        if (File.ReadAllBytes(logFile).Length == 0)
        {
            Console.WriteLine("Log file is empty.");
        }
        else
        {
            using (StreamReader r = File.OpenText(logFile))
            {
                while ((line = r.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
                Console.WriteLine();
            }
        }
    }
}

Solution

  • In method CreateLog, you're trying to read a file with File.ReadAllBytes. However, this file has been open by File.AppendText before read operation, that's why exception occurs. You can check if file empty before writing operation to avoid this exception.

    Please refer to code below for part of method CreateLog.

                bool isFileEmpty = File.ReadAllBytes(logName).Length == 0;
                using (StreamWriter logCreate = File.AppendText(logName))
                {
                    if (isFileEmpty)
                    {
                        logCreate.WriteLine($"Monitored: {path} {time}");
                    }
                    else
                    {
                        logCreate.WriteLine($"\nMonitored: {path} {time}");
                    }
                }