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.
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 }