views:

80

answers:

3

I have an application that runs as a Windows service. It stores various things settings in a database that are looked up when the service starts. I built the service to support various types of databases (SQL Server, Oracle, MySQL, etc). Often times end users choose to configure the software to use SQL Server (they can simply modify a config file with the connection string and restart the service). The problem is that when their machine boots up, often times SQL Server is started after my service so my service errors out on start up because it can't connect to the database. I know that I can specify dependencies for my service to help guide the Windows service manager to start the appropriate services before mine. However, I don't know what services to depend upon at install time (when my service is registered) since the user can change databases later on.

So my question is: is there a way for the user to manually indicate the service dependencies based on the database that they are using? If not, what is the proper design approach that I should be taking? I've thought about trying to do something like wait 30 seconds after my service starts up before connecting to the database but this seems really flaky for various reasons. I've also considered trying to "lazily" connect to the database; the problem is that I need a connection immediately upon start up since the database contains various pieces of vital info that my service needs when it first starts. Any ideas?

A: 

Dennis what your looking for is SC.exe. This is a command line tool that users can use to configure services.

sc [Servername] Command Servicename [Optionname= Optionvalue...]

more specificly you would want to use

sc [ServerName] config ServiceName depend=servicetoDependOn

Here is a link on the commandlike options for SC.EXE http://msdn.microsoft.com/en-us/library/ms810435.aspx

John Hartsock
Thanks this will certainly help. This isn't quite ideal as I now have to instruct my end users to run this command, but it is better than nothing.
Dennis
A: 

A possible (far from ideal) code solution:

In you startup method code it as a loop that terminates when you've got a connection. Then in that loop trap any database connection errors and keep retrying as the following pseudo code illustrates:

bool connected = false;
while (!connected)
{
    try
    {
        connected = openDatabase(...);
    }
    catch (connection error)
    {
         // It might be worth waiting for some time here
    }
}

This means that your program doesn't continue until it has a connection. However, it could also mean that your program never gets out of this loop, so you'd need some way of terminating it - either manually or after a certain number of tries.

As you need your service to start in a reasonable time, this code can't go in the main initialisation. You have to arrange for your program to "start" successfully, but not do any processing until this method had returned connected = true. You might achieve this by putting this code in a thread and then starting your actual application code on the "thread completed" event.

ChrisF
I don't think this will help as the Windows service manager will wait for my service to complete its start up before attempting to start the next service...
Dennis
@Dennis - good point.
ChrisF
A: 

Not a direct answer put some points you can look into

  1. Windows service can be started Automatically with a delay. You can check this question in SO for some information about it.

How to make Windows Service start as “Automatic (Delayed Start)”

  1. Check this post How to: Code Service Dependencies
Shoban
Thanks for the delayed start link. Unfortunately that is only available on Vista and later so it won't work for my users that are using XP and Server 2003.
Dennis