Aleksei Chepovoi
Aleksei Chepovoi

Reputation: 3955

windows service strange behavior

I implemented windows service with eventLog and FileSystemWatcher that looks for changes in specific directory and writes messages into MyLog.

strange thing 1:
I install it via installUtil.exe (since the VS2012 doesn't have installer templates) and in some situations when I go to "Services" and start the service I get:

The [service name] service on local computer started and then stopped. Some Services stop automatically if they are not in use by another services or programs.

I've already seen this question. 2 answeres from this post why it can be so:

1) There is no thread starting in OnStart() method.
I use the designer and set most of the properties in the Properties window and I never started any thread manually, but in some cases everything was working, so I think this is not the case.

2) An exception occures in OnStart() method. I think it's not the case cause I don't change the code. I just uninstall, build and install again the same service and in some cases it runs, in some not.

When I was stuck for mabby 2 hours with this thing I noticed that the Source property of eventLog is too long: "FilesMonitoringServices". I changed it to "MonitorSource" and everything started to work. Than I reinstalled it cauple of times and got the same warning as the above. I changed the Source property again and now the service runs.
This is the first strange thing.

strange thing 2: worse. Even if it runs it logs only OnStart() and OnStop() methods, I mean the fileSystemWatcher event handler never excutes. It is strange because today I reinstalled this service mabby hundred times and 3 times it was working but after I reinstalled it once again it stoped. And I haven't changed the code between the reinstallations at all.

Here is the methods and constructor from my class (MonitoringService) that inherits ServiceBase:

public MonitoringService()
    {
        InitializeComponent();

        if (!EventLog.SourceExists(eventLog.Source))
        {
            EventLog.CreateEventSource(eventLog.Source, eventLog.Log);
        }
        // haven't changed it between the reinstallations
        fileWatcher.Path = @"path";                
    }

protected override void OnStart(string[] args)
    {
        fileWatcher.EnableRaisingEvents = true;
        eventLog.WriteEntry("start", EventLogEntryType.Information);
        base.OnStart(args);
    }

    protected override void OnStop()
    {
        fileWatcher.EnableRaisingEvents = false;
        fileWatcher.Dispose();
        eventLog.WriteEntry("stop", EventLogEntryType.Information);
        base.OnStop();
    }

And file system watcher event handler:

private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
    {
        using (var conn = new SqlConnection(GetConnectionString()))
        {
            conn.Open();
            var productId = Convert.ToInt32(Regex.Match(e.Name, @"\d+").Value);
            const string cmd = "UPDATE Products SET ImageModifiedDate=@date WHERE ProductId=@productId";
            using (var command = new SqlCommand(cmd, conn))
            {
                command.Parameters.AddWithValue("@productId", productId);
                command.Parameters.AddWithValue("@date", DateTime.Now);
                command.ExecuteNonQuery();
            }                   
        }
        eventLog.WriteEntry(string.Format("{0} has been changed: {1}", e.Name, DateTime.Now), EventLogEntryType.Information);             
    }

Question: it seems to me that this behavior is caused not by my code but rather by operation system settings . Can it be so?

****Edits: just discovered more specific stuff:**

1) If it shows the message (when I want to start the service):

The [service name] service on local computer started and then stopped. ....

I need to change Source property of eventLog, rebuild and reinstall. And this message will not show up; mabby next time.

2) I have the following folders hierarchy: images/prod-images. images and prod-images directories both contain image files. When the service is runing and I change the image from prod-images folder the message is written into the log as I wanted and the database is updated. But after one this event the service stops! (I checked this 3 times). And when I restart it and repeat this again a couple of times it updates database, writes logs and on the 3d time I get

The [service name] service on local computer started and then stopped. ....

But this is not the best part) If I change the image that is in images directory I can do it multiple times and the service doesn't stop. (only images from images/prod-images are bound to entries in the database).

So, mabbe this feature somehow referes to the database accessing?

Edits 2: in visual studio I use DEBUG -> Attach to Process to debug the service. I set up the breakpoints and change the image. First time the event handler executes flawlessly: the database is updated and the log message is written. But than I continue to press F11 (Step Into) and this event handler executes second time. At the line

var productId = Convert.ToInt32(Regex.Match(e.Name, @"\d+").Value); 

I get "FormatException was unhandled". After this I stop debugging and the service stops! That's it: the exception occures in event handler.

Do You have any idea why it executes second time? Thanks!

P.S. I've already submited Davut Gürbüz answer cause he pointed me in the right direction.
Anyway, check out my own answer that explains the actual problem.

Upvotes: 2

Views: 2056

Answers (2)

Aleksei Chepovoi
Aleksei Chepovoi

Reputation: 3955

The reason why the fileSystemWatcher1_Changed event handler method was executing twice is because I was monitoring images folder included subdirectories. And this event handler was monitoring all LastWrite events.

So, when I changed the image in images/prod-images directory this handler reacted to the image changing and also to the folder changing.

In this situation I either can change the monitoring path to prod-images or insert an if statement when updating the DB.

Such a silly mistake took me a couple of days to find it out))

Upvotes: 0

Davut Gürbüz
Davut Gürbüz

Reputation: 5736

If you got start-stop error, this means you have an error in constructor.

Put a try catch into your ctor. You may log the error to eventlog in catch block.

Beside this I create a main method and start win service as a console app. If I get an instance of service in my main method I can also Debug it.

//You should select Console Application from Application properties
static void Main(string[] args)
    {
        MyWindowsService service = new MyWindowsService();

        if (Environment.UserInteractive)
        {
            service.OnStart(args);
            Console.WriteLine("Press any key to stop program");
            Console.Read();
            service.OnStop();
        }
        else
        {
            ServiceBase.Run(service);
        }

    } 

Hope helps

Upvotes: 2

Related Questions