Philippsen's Blog

Everyday findings in my world of .net and related stuff

Posts Tagged ‘System.IO’

FileSystemWatcher problem – file is in use by another process

Posted by Torben M. Philippsen on October 25, 2010

Recently I was developing a simple windows service that was supposed to monitor a certain folder for incomming xml files. When Xml files were received, the xml content should be send to a http endpoint – pretty straight forward.

The FileSystemWatcher was created like this:

    1  /// <summary>

    2         /// Creates a filesystem watcher listening for new xml files. An event is rised, if a new file is created in the watched folder

    3         /// </summary>

    4         private void CreateFileSystemWatcher()

    5         {

    6             watcher = new FileSystemWatcher();

    7             watcher.Path = ConfigurationManager.AppSettings[“xmlFilePath”];

    8             // Only watch xml files.

    9             watcher.Filter = “*.xml”;

   10             // Add event handlers.           

   11             watcher.Created += new FileSystemEventHandler(OnCreated);

   12             //watcher.Changed += new FileSystemEventHandler(OnCreated);

   13             // Begin watching.

   14             watcher.EnableRaisingEvents = true;

   15         }

 

The eventhandler looked like this:

   20         /// <summary>

   21         /// Eventhandler – handles the event where a new file is created in the watched folder

   22         /// </summary>

   23         /// <param name=”source”></param>

   24         /// <param name=”e”></param>

   25         private void OnCreated(object source, FileSystemEventArgs e)

   26         {           

   27             // Specify what is done when a file is created.

   28             XmlDocument doc = GetXmlDocumentFromFile(e.FullPath);

   29             StatusObj result = Post(doc);

   30             ProcessResult(result, e.FullPath, e.Name);           

   31         }

 

I quickly discovered that I would receive an exception when trying to read the xml content from the file that triggered the event. I found that the reason to this issue is that when the “create” event is triggered the file hasn’t finished to be written to the folder. The process that writes the file to the folder, will still have an active filehandle causing the “Access denied” exception.

In my search for a “good” solution I read that some would recomment to use the “change” event of the FileSystemWatcher. I haven’t been able to get this to work and You should be aware that using the change event will cause your eventhandler to trigger at least twice when a file is written to the monitored folder.
The best solution I found was to make a function that checks if the file can be read or not – something like this:
 

   40         /// <summary>

   41         /// Helper method used to check if the file has been released from the os

   42         /// </summary>

   43         /// <param name=”file”></param>

   44         /// <returns></returns>

   45         public bool IsFileInUse(FileInfo file)

   46         {

   47             FileStream stream = null;

   48             try

   49             {

   50                 stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);

   51             }

   52             catch (IOException)

   53             {

   54                 //the file is unavailable because it is:

   55                 //still being written to

   56                 //or being processed by another thread

   57                 //or does not exist (has already been processed)

   58                 return true;

   59             }

   60             finally

   61             {

   62                 if (stream != null)

   63                     stream.Close();

   64             }

   65             //file is not locked

   66             return false;

   67         }

 

And then use it like this:

   80         /// <summary>

   81         /// Reads the xml structure from the physical file into a XmlDocument object

   82         /// </summary>

   83         /// <param name=”filename”>the full path of the xmlfile</param>

   84         /// <returns></returns>

   85         private XmlDocument GetXmlDocumentFromFile(string filename)

   86         {

   87             XmlDocument xDoc = new XmlDocument();

   88             while (IsFileInUse(new FileInfo(filename)))

   89             {

   90                 //loop until filehandle is released

   91                 Thread.Sleep(500);

   92             }

   93             try

   94             {

   95                 xDoc.Load(filename);

   96             }

   97             catch (Exception ex)

   98             {

   99             }

  100             return xDoc;

  101         }

I know that using exception handling to control a certain flow isn’t concidered best practice – but unfortunately this was the best I could come up with. Should You have a better way – please leave a note…

Advertisements

Posted in System.IO | Tagged: , | 2 Comments »

 
%d bloggers like this: