Windows Service that monitors a folder

Hi everyone

I'm trying to create a Windows Service that monitors a given directory.  Whenever a file is dropped inside that directory, it processes that file.

When I created this service (using the walkthrough on MSDN) and installed it, it timed out when I tried to start it.  It *was* processing the files dropped in the directory, but its status in the MMC was "starting" rather than "started."

I'm assuming I need to return control to the OS somehow, but how?  I thought FileSystemWatcher is non-blocking.  Do I need to launch a new thread?

Here's the main monitoring function for my application (called through OnStart in the service):

private void Monitor(string path)
{
  // The file monitor for the semaphore directory
  FileSystemWatcher watcher = new FileSystemWatcher(path);

  watcher.NotifyFilter = NotifyFilters.LastWrite |
    NotifyFilters.DirectoryName | NotifyFilters.FileName;
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.EnableRaisingEvents = true;

    // Wait for changes in the semaphore directory
    while(true)
    {
      watcher.WaitForChanged(WatcherChangeTypes.All);
    }
}
yizchaknavehAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AaronReamsCommented:
You should do your Monitor in a separate thread so the call to OnStart can return successfully to the service manager.

WaitForChange is a blocking/synchronous function.  However, even if it was asynchronous/non-blocking, your code would effectively make it blocking because of the infinite while loop.

So just fire up a separate thread and you're good to go.

Hope this helps.
-Aaron
0
s_sansanwalCommented:
You need to run this in a separate thread as your application is stuck in While loop

Cheers,
S Sansanwal
0
s_sansanwalCommented:
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

AaronReamsCommented:
This should help you get started with a thread so your service can start succesfully.  Cheers -A.

private void Monitor(string path)
{
       ServerInstanceThread s = new ServerInstanceThread(path);
       Thread sThread = new Thread(new ThreadStart(s.ThreadProc));
       sThread.IsBackground = true;
       sThread.Start();
}

public class ServerInstanceThread
{
     public string path;
     public ServerInstanceThread(string _path)  { path = _path;}

      public void ThreadProc()
      {
           // The file monitor for the semaphore directory
           FileSystemWatcher watcher = new FileSystemWatcher(path);

          watcher.NotifyFilter = NotifyFilters.LastWrite |
          NotifyFilters.DirectoryName | NotifyFilters.FileName;
          watcher.Created += new FileSystemEventHandler(OnChanged);
          watcher.EnableRaisingEvents = true;

          // Wait for changes in the semaphore directory
          while(true)
          {
              watcher.WaitForChanged(WatcherChangeTypes.All);
          }  
      }
}
0
Fahad MukhtarDistinguished EngineerCommented:
There is no need for this listener Loop you can acheive the funcitionlaity without this:

   // Wait for changes in the semaphore directory
   while(true)
   {
     watcher.WaitForChanged(WatcherChangeTypes.All);
   }
0
Fahad MukhtarDistinguished EngineerCommented:
Heres what i did for a similar Windows Service i suppose...


protected override void OnStart(string[] args)
            {                  
                  Watcher = new FileSystemWatcher();
            Watcher.Path = ReportsPhysicalFolder ;//put your folder to watch here

                  Watcher.NotifyFilter = NotifyFilters.DirectoryName;
                  Watcher.NotifyFilter = Watcher.NotifyFilter | NotifyFilters.FileName;
                  Watcher.NotifyFilter = Watcher.NotifyFilter | NotifyFilters.Attributes;

                  //add the handler to each event                  
                  
                  Watcher.Changed +=  new FileSystemEventHandler (this.  logchange);
                  Watcher.Created +=  new FileSystemEventHandler (this.  logchange);
                  Watcher.Deleted +=  new FileSystemEventHandler (this.  logchange);

                  // add the rename handler as the signature is different
                  Watcher.Renamed += new  RenamedEventHandler  (this.  logrename);

                  //Set this property to true to start watching
                  Watcher.EnableRaisingEvents = true;            
            }
 
            /// <summary>
            /// Stop this service.
            /// </summary>
            ///             
            protected override void OnStop()
            {
                  Watcher.EnableRaisingEvents = false;
            }

            private void logchange ( object source , FileSystemEventArgs e)
            
            {      
                  try
                        {
                              if (e.ChangeType == WatcherChangeTypes.Created)
                              {
                                    ServiceWriteToFile ("NEW REPORT!!! Report \"" + e.Name + "\" has been added to the Application.");                              
                              }
       
                              if (e.ChangeType == WatcherChangeTypes.Deleted )
                              {
                                    ServiceWriteToFile ("REPORT DELETED!!! Report \"" + e.Name + "\" has been removed from the Application.");
                              }
                        }

                        catch (XmlException rr)
                        {
                              ServiceWriteToFile("XML ERROR Occured During Processing  : " + rr.Message +  RecordSepartor + "\r\n");
                        }

                        catch (SqlException ss)
                        {
                              ServiceWriteToFile("DATABASE ERROR Occured During Processing : " + ss.Message +  RecordSepartor + "\r\n");                              
                        }                        
                        
                        catch (Exception ss)
                        {
                              ServiceWriteToFile("ERROR Occured During Processing : " + ss.Message +  RecordSepartor + "\r\n");                              
                        }
            }

            private void logrename ( object source , RenamedEventArgs e)
            {
                        try
                        {
                              ServiceWriteToFile ("REPORT NAME CHANGED!!! Report \"" + e.OldName + "\" has been renamed to \"" + e.Name + "\"");
                        }

                        catch (XmlException rr)
                        {
                              ServiceWriteToFile("XML ERROR Occured During Processing  : " + rr.Message +  RecordSepartor + "\r\n");
                        }

                        catch (SqlException ss)
                        {
                              ServiceWriteToFile("DATABASE ERROR Occured During Processing : " + ss.Message +  RecordSepartor + "\r\n");                              
                        }                        
                        
                        catch (Exception ss)
                        {
                              ServiceWriteToFile("ERROR Occured During Processing : " + ss.Message +  RecordSepartor + "\r\n");                              
                        }
            
            }


ServiceWriteToFile()  is my user defined function
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Razzie_Commented:
Hi yizchaknaveh,

I, and other people, have experienced the exact same problems when starting a windows server. Take a look at this question:

http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_21133967.html

I gave some possible solutions there that helped me and some other people. I advice you give it a shot. As far as I know, this is not a problem with your code in anyway, but rather a bug in Windows. Let me guess, are you installing the service under Windows 2000?

Cheers,

Razzie
0
gregoryyoungCommented:
The OnStart() method is called while starting your service. You are not supposed to block or take control at this point because if you do you will never return control to ServiceBase to allow for the completion of the start process.
0
yizchaknavehAuthor Commented:
Wow!  Thanks to all who responded.  The app works now, and I got rid of the ugly infinite loop. :)

Points split.

Razzie: no, I was installing on XP Pro
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.