Search code examples
windows-7windows-servicesstreamreaderfilesystemwatcher

Cannot read two consecutive files with a Windows Service using StreamReader object


I need to be able to read lines of a file with a StreamReader processed by a FileSystemWatcher in a Windows service.

I've read and tried everything that made sense online, but it still doesn't work. When I'm attahced to my Windows service process (local machine using Visual Studio 2010), the whole thing works flawlessly!

When I try to run it (on my local machine) without attaching to it and debugging it, the second file never makes it through and I get the following msg: "The process cannot access the file 'C:\Projects\Data\VendingStats\20121213_AZM_Journey_MIS.txt' because it is being used by another process." I do not have this file open anywhere else on my machine. It is just sitting in a directory. I then copy it in a directory and the FSW takes over (and the code below).

Can someone please tell me what I need to do to get this to work? I don't know why it works fine when I'm attached to and debugging it, but it doesn't work when I send the files through without being attached and debugging it. I feel it's defeintiely something on my local box that I need to disable, etc --- I don't know.....

I noticed that the error occurs even before it gets into the "using" statement, because the second file is never copied to the temp directory for it to be processed.

I noticed in my StackTrace, I'm getting the following error: system.io.__error.winioerror(int32 errorcode string maybefullpath)

Here is my code:

protected override void OnStart(string[] args)
        {
            FileSystemWatcher Watcher = new FileSystemWatcher(@"C:\Projects\Data\VendingStats");
            Watcher.EnableRaisingEvents = true;
            Watcher.Created += new FileSystemEventHandler(Watcher_Created);
            Watcher.Filter = "*.txt";
            Watcher.IncludeSubdirectories = false;
        }

private void Watcher_Created(object sender, FileSystemEventArgs e)
        {
            try
            {
                string targetPath =  @"C:\Temp\VendorStats";

                // Use Path class to manipulate file and directory paths. 
                FileInfo fi = new FileInfo(e.FullPath); // full name of path & file in the FSW directory
                string destFile = Path.Combine(targetPath, fi.Name);

                // To copy a folder's contents to a new location: 
                // Create a new target folder, if necessary. 
                if (!Directory.Exists(targetPath))
                    Directory.CreateDirectory(targetPath);

                // To copy a file to another location and  
                File.Copy(e.FullPath, destFile, true);

                // Set attribute to READONLY
                if (fi.IsReadOnly == false)
                    fi.Attributes = FileAttributes.ReadOnly;

                GetCruiseLineShipName(destFile, ref cruiseLine, ref shipName);

                using (StreamReader sr = new StreamReader(File.Open(destFile, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    filename = e.FullPath;

                    //How many lines should be loaded?
                    int NumberOfLines = 39;

                    //Read the number of lines and put them in the array
                    for (int i = 1; i < NumberOfLines; i++)
                    {
                        ListLines[i] = sr.ReadLine();
                        switch (i)
                        {
                            case 3:
                                int idx = ListLines[i].IndexOf(":");
                                string timeLine = ListLines[i].Substring(idx + 1);
                                dt = GetDate(Convert.ToDateTime(timeLine.Substring(1)));
                                break;

                            //more code here of the same                        
                        }
                    }
                    //InsertData into database                }
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("VendorStats", "Error in the Main:" + "\r\n\r\n" + ex.Message + "\r\n\r\n" + ex.InnerException);
                return;
            }
        }

Solution

  • The bottom line to solving this was to put the method (that was spawned by the FileSystemWatcher) to sleep for "X" amount of seconds until Windows completely releases the resources to the previous and present files as well as the folder.

    It was the FileSystemWatcher that actaully had a hold on the resources.

    Here is some sample code:

    private static void Watcher_Created(object sender, FileSystemEventArgs e)
            {
                try
                {
                    Thread.Sleep(10000);
    
                    GetCruiseLineShipName(e.FullPath, ref cruiseLine, ref shipName);
    
                    using (StreamReader sr = new StreamReader(File.Open(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read)))
                    {