28

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?

Community
  • 1
  • 1
dp.
  • 8,138
  • 7
  • 33
  • 28
  • Is there any particular reason other than "I want to" that you need to have the services in a single executable? Normally, modularity would be preferable, but you may have extenuating circumstances that require otherwise. – bsneeze May 03 '09 at 06:10
  • The only real reason is for ease of installation and deployment. All of the "services" are fairly quick one off pieces of functionality, so I'd prefer not to have to install x number of windows services for small pieces of code. – dp. May 04 '09 at 02:52
  • @pyrochild -- I'm confident there are numerous reasons to mount multiple services within a single assembly. Where I work now we use beasts of that design on a per-customer basis -- it makes testing software that interacts with those services a breeze. – Hardryv Sep 06 '11 at 13:19
  • [This might help](http://www.bryancook.net/2008/04/running-multiple-net-services-within.html) – Nilay Vishwakarma Dec 21 '16 at 10:47

7 Answers7

15

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
  • 2,183
  • 18
  • 33
5

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
  • 51
  • 1
  • 2
  • I had to use the detail here to tell me how to do this: https://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx For the lazy: "Open the context menu for the designer window (if you’re using a pointing device, right-click inside the window), and then choose Add Installer." – wilsjd Mar 08 '16 at 19:06
  • @RitwikSen, I think he is referring to a project type that was available at the time or writing (2009), which produced program install wizards for end users. This was removed starting from VS2012, but still available as an extension on the VS marketplace. But I'd recommend using something else for that, as it produces really oldish UI, and has a bug with 64bit applications. – Tsahi Asher Jun 25 '18 at 08:07
2

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...

1

I used sc.exe to accomplish this easily. http://support.microsoft.com/kb/251192

For ex: sc create "My Display Service Name" binpath= "c:\app\mysvc.exe --service"

Note: every equal should have space before its value as you can see for 'binpath'

Community
  • 1
  • 1
Pavan G R
  • 306
  • 3
  • 16
  • In case anyone got here like me and wanted to make this works with sc.exe (thus, without an installer): That ``--service`` in the end of the binpath is a parameter that you can add to your service Main method. There, you can switch which service you want to start based on such parameter. [More info here](https://www.codeproject.com/Tips/791343/Run-multiple-instances-of-a-Windows-service) – Gabriel Rainha Apr 24 '20 at 22:54
1

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.

Steven Evers
  • 16,649
  • 19
  • 79
  • 126
0

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
  • 2,540
  • 2
  • 30
  • 38
-1

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