views:

1075

answers:

6

I am trying to build several Windows services to do different things. For instance, I need Windows services that will:

  1. Send a daily report via email
  2. Periodically cleanup some archived info every 30 minutes
  3. etc.

The tasks I need the windows services to do are distinct so I don't really like the idea of having them all in one service.

What I've got so far is a project in Visual Studio 2008. I've created a windows service, I've set up a timer on the OnStart event (it just writes to a text file every 5 seconds for testing purposes). I then added an Installer to the project and when I run InstallUtil.exe, everything works fine.

The problem comes in when I add a second windows service to the same project. I set up the OnStart code again, with the same logging info (slightly different so I can tell which service is writing to the log). With the second windows service, I changed the Main event in Program.cs from:

    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun = new ServiceBase[] 
        { 
            new Service1()
        };

        ServiceBase.Run(ServicesToRun);
    }

to:

    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun = new ServiceBase[] 
        { 
            new Service1(),
            new Service2()
        };

        ServiceBase.Run(ServicesToRun);
    }

At this point, there are no compile time errors, but the Service2 service never does anything...the logging task never fires.

I narrowed it down to the fact that the second service has no "Installer" associated with it. I then tried to add an Installer the way I did with the first service (i.e., right click on the service designer, and click "Add Installer"). Now, when I go to the ProjectInstaller.cs file, there is another serviceInstaller there (serviceInstaller2).

Now when I build the project and try to install the services, and I go to the "Services" control panel window, and I try to start Service1, I get the following error message:

Windows could not start the Service1 service on the Local Computer.

Error 1083: The executable program that this service is configured to run in does not implement the service.

I get the same error message if I try to start Service2 as well (with the exception that the error message identifies Service2, of course).

Is there something I am missing in order to get two services running from one exe?

+1  A: 

I'm actually building something very similar to what you're thinking of. What I've decided to do (thus far) is have all of my 'services' (though they aren't services, the one 'controller' is) implement a particular interface (with init() and execute() operations as well as a FREQUENCY enumeration).

The controller is the windows service and it reads the list of programs/dlls from an xml settings file at runtime and loads them into a List and calls their execute() method (if applicable) on whatever frequency they have defined.

In my case, each program also contains a usercontrol that is loaded into a tab page of the controller that allows the user to control/modify it. I'll post code if you're interested.

Not sure if that was clear. I actually got the idea from another SO user who implemented something similar but I can't find that post now.

SnOrfus
+1  A: 

I had a similar problem today, and managed to resolve it.

Firstly, I made sure that each of the services had a meaningful and unique ServiceName property. The generator gave both of the services the same name which would not have helped.

I then removed and regenerated the ProjectInstaller class, and added installers for each of the classes. I made sure they were both instantiated in the static Main method.

I can now install the two services with the one dll, but unfortunately when I start one of the services it seems to perform the functions of both itself and the other service. That is, both of the services are running (even though only one of the services appears as 'Started' in Computer Manager). I'm still trying to figure that one out...

A: 

I had the same problem today and managed to fix it. In my case I just had to open the *.designer.cs files of my services and make sure that the service name is set correctly. More importantly the same name should be used in the *Installer.Designer.cs and if you have code in *Installer.cs.

I think this error occurs only because of name mismatch.

Hope this helpds

Usman Akram
A: 

I guess that you guys have already solved this, but in case that some else needs it, I'll post an answer to this issue which took me several hours today. The solutions is not to add another project installer, but a service installer, which is a component on the project installer. That newly added service installer has to have second service name configured.

Ogren
+1  A: 

I have figured out how to have one executable but two services. Each service installs to the service manager with its own name and ability to start/stop. I think this is what you're wanting, correct? Here is what I did:

  1. Created a service project.
  2. Added a second service to the same project (with a unique service name).
  3. Added an installer to both services (ServiceA and ServiceB).
  4. In the ProjectInstaller.Designer.vb file I changed the Me.Installers.AddRange line to show both of the service installers. (Me.ServiceInstaller1, Me.ServiceInstaller2)
  5. In the Main entry point of the main service (ServiceA in my case), I set the ServicesToRun variable to an array of ServiceBase containing all the services that I want it to run (ServiceA and ServiceB). This is an important step as the service manager sets a property based on the number of arguments here - either to allow multiple instances of the same exe or only a single instance.
  6. Add an installer project and use the output of Services.
  7. Add a custom action using the output from Services.

You can find the demo code here:
http://code.google.com/p/multi-service-install/

Enjoy!

Scott
A: 

Installing 2 distinct and unrelated services in one executable has a funny smell to me. While it's possible to get it to work, it doesn't make it right.

From what it sounds like, you need to perform some different tasks at various intervals and your tasks may or may not be related. Have you looked into Quartz.NET? It sounds like a good fit for your needs.

http://quartznet.sourceforge.net/features.html

Walter