tags:

views:

346

answers:

6

I'm writing a Windows service that relies on other services, how should I wait for the other services to start?

Thanks

+1  A: 

You need to specify the dependencies. You can do this in your Installer class.

Further clarification

You should be using an Installer class as a Custom Action in your setup project to install your service. If you aren't, post a comment and I'll update this answer with steps on how to do that.

Inside the designer for your Installer class you should see two components: a serviceInstaller and a serviceProcessInstaller. I don't remember which off of the top of my head, but one of these has a property that allows you to specify a multiline string that lists the service names of your service's dependencies.

Adam Robinson
Could you clarify what you mean? How would this help me? Thanks
When installing the service using the ServiceInstaller (http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx) class, you can add dependencies using the ServicesDependedOn property.
adrianbanks
+1  A: 

I think you shoud this line

installer.ServicesDependedOn = new string [] { "DependenceService" };

like this:

using (ServiceProcessInstaller processInstaller = new ServiceProcessInstaller())

{

processInstaller.Account = ServiceAccount.LocalSystem;
processInstaller.Username = null;
processInstaller.Password = null; 

using (ServiceInstaller installer = new ServiceInstaller())

{
    installer.DisplayName = "yourservice.";
    installer.StartType = ServiceStartMode.Automatic;
    installer.ServiceName = "YourService";



    installer.ServicesDependedOn = new string [] { "DependenceService" };
    this.Installers.Add(processInstaller);
    this.Installers.Add(installer);

}

}

goof luck

Jonathan
Dependent services get started automatically when your service starts, but your service isn't started automatically when they already run. And that was the question as I understood it.
devdimi
ops... I'm sorry if I missunderstood the problem.
Jonathan
I know this a clean solution, but as a workaround we could check the wanted service status every N seconds:ServiceController Name = new ServiceController();byServiceName.ServiceName = "ServiceWanted";and then:if (name.Status == ServiceControllerStatus.Running){ //perform actions of the service}
Jonathan
Is there a reason you'd do this programatically rather than through the designer?
Adam Robinson
No, there isn't. The designer will do the same work.
Jonathan
A: 

Do you have control over the other services? If yes have them start you, if not I guess you have to start anyway and monitor yourself what is going on. It is possible to register yourself with WMI to get notifyied when other processes are started - there is a question about it.

devdimi
There's a way to specify the service dependencies to windows, so it doesn't try to start your service until the other services have finished startup.
Bevan
That is right, however it does not help you if you want your service to be started only when other services already run - and I think that was the question.
devdimi
@dev: in what way does it not? Set the dependencies and the startup type to Automatic.
Adam Robinson
+1  A: 

In addition to what other answers have alredy pointed out, if one of those services is SQL Server you will need to ensure that the specific database is available as well as the SQL Server service itself. I use a function similar to the following:

public class DbStatus
{
    public static bool DbOnline()
    {
        const int MaxRetries = 10;
        int count = 0;

        while (count < MaxRetries)
        {
            try
            {
                // Just access the database. any cheap query is ok since we don't care about the result.
                return true;
            }
            catch (Exception ex)
            {
                Thread.Sleep(30000);
                count++;
            }
        }
        return false;
    }
}
Kim Major
A: 

In your service project, add a project installer as described here. One of the properties of your ProjectInstaller will be ServicesDependedOn. When you add services to that array of strings (you can do that through the IDE), they will be required to be started before your service will start. If they are not started the SCM will try and start them.

JP Alioto
+1  A: 

As others here said, you should use the ServiceInstaller Class, but you don't need a full blowned setup project. You can do a quick instalation using InstallUtil.exe, a command-line utility that comes with the .NET Framework.

Alfred Myers