55

What is the easiest language to build Windows services in?

Easiest in this case would be defined as least amount of code, and lowest point of entry into the language.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
UnkwnTech
  • 79,308
  • 64
  • 178
  • 223

6 Answers6

185

At the risk of stating the obvious, if you have any C/C++/Java background, I think C# offers you the lowest point of entry.

Assuming you're using Visual Studio 2008, you can follow these steps:

  1. Open Visual Studio 2008, and select the File|New|Project menu option.
  2. In the New Project dialog...
    • Select the Visual C#|Windows node in Project types
    • Select the Windows Service template
    • Enter a name and location for your project
    • Press OK
  3. At this point, you have all the basics for your Windows service. The Program.cs file contains the Main() method for your service, and Service1.cs defines the System.ServiceProcess.ServiceBase component that is your new Windows service.
  4. In the Property Grid for your Service1 component, consider setting the following properties at a minimum:
    • (Name) - give your object an intuitive name, e.g., ServiceExample
    • AutoLog - set to false to prevent events from being written by default to the Application event log (Note: I'm not saying you shouldn't log service events; I just prefer writing to my own event log instead of the Application log - see below)
    • CanShutdown - set to true if you want to handle system shutdowns
    • ServiceName - defines the name by which your service will be known to the Service Control Manager (SCM)
  5. In the code for ServiceExample, the OnStart() and OnStop() virtual functions are stubbed out. You'll need to fill these in with whatever your service needs to do obviously. If you changed the CanShutdown property to true, you'll want to override the OnShutdown method as well. I've created an example below illustrating the use of these functions.
  6. At this point, the ServiceExample service is essentially complete, but you still need a way to install it. To do this, open the ServiceExample component in the designer. Right-click anywhere in the designer panel, and select the Add Installer menu option. This adds a ProjectInstaller component to your project, which contains two additional components - serviceProcessInstaller1 and serviceInstaller1.
  7. Select the serviceProcessInstaller1 component in the designer. In the Property Grid, consider setting the following properties:
    • (Name) - give your object an intuitive name, e.g., serviceProcessInstaller
    • Account - select the LocalService account as a minimum, but you may have to use the NetworkService or LocalSystem account if your service requires more privileges
  8. Select the serviceInstaller1 component in the designer. In the Property Grid, consider setting the following properties:
    • (Name) - give you object an intuitive name, e.g., serviceInstaller
    • Description - the service's description which will show up in the SCM for your service
    • DisplayName - the friendly name for your service which will show up in the SCM for your service
    • ServiceName - make sure this is the same name that you selected for the ServiceName property of your ServiceExample component (see Step 4)
    • StartType - indicate if you want the service to start automatically or manually
  9. Remember that I said I prefer writing events to my own event log instead of the Application event log. To do this, you'll need to replace the default EventLogInstaller in your ProjectInstaller with a custom one. Make your code for your ProjectInstaller look like this:

using System.Diagnostics;
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
    public ProjectInstaller()
    {
        InitializeComponent();

        EventLogInstaller installer = FindInstaller(this.Installers);
        if (installer != null)
        {
            installer.Log = "ServiceExample"; // enter your event log name here
        }
    }

    private EventLogInstaller FindInstaller(InstallerCollection installers)
    {
        foreach (Installer installer in installers)
        {
            if (installer is EventLogInstaller)
            {
                return (EventLogInstaller)installer;
            }

            EventLogInstaller eventLogInstaller = FindInstaller(installer.Installers);
            if (eventLogInstaller != null)
            {
                return eventLogInstaller;
            }
        }
        return null;
    }
}

At this point, you can build your project to get your Windows service executable. To install your service, open the Visual Studio 2008 command prompt, and navigate to the Debug or Release directory where your executable is. At the command prompt, type the following: InstallUtil ServiceExample.exe. This will install your service on the local machine. To uninstall it, type the following at the command prompt: InstallUtil /u ServiceExample.exe

As long as your service is not running, you can make changes to your service and re-build, i.e., you do not have to uninstall your service to make changes to it. However, you will be unable to overwrite the executable with your fixes and enhancements as long as it is running.

To see your service in action, open the ServiceExample.cs file and make the following changes:

using System.Diagnostics;
public partial class ServiceExample : ServiceBase
{
    public ServiceExample()
    {
        // Uncomment this line to debug the service.
        //Debugger.Break();

        InitializeComponent();

        // Ties the EventLog member of the ServiceBase base class to the
        // ServiceExample event log created when the service was installed.
        EventLog.Log = "ServiceExample";
    }

    protected override void OnStart(string[] args)
    {
        EventLog.WriteEntry("The service was started successfully.", EventLogEntryType.Information);
    }

    protected override void OnStop()
    {
        EventLog.WriteEntry("The service was stopped successfully.", EventLogEntryType.Information);
    }

    protected override void OnShutdown()
    {
        EventLog.WriteEntry("The service was shutdown successfully", EventLogEntryType.Information);
    }
}

Once you run your service with these changes, you can look at the ServiceExample event log in the Event Viewer and see the messages logged there.

Hope this helps.

EDIT: If you prefer to use the Application event log for your event logging instead of a custom one, simply make no changes to the ProjectInstaller.cs file. In addition, leave out the line that sets the Log property of the EventLog in the ServiceExample constructor. When you run your service, your log messages will appear in the Application event log.

Matt Davis
  • 43,149
  • 15
  • 89
  • 118
  • 5
    To have the service install itself from the command line instead of having to use the InstallUtil.exe, refer to my post here: http://stackoverflow.com/questions/1195478/how-to-make-a-net-windows-service-start-right-after-the-installation/1195621#1195621 – Matt Davis Nov 16 '09 at 14:51
  • how can I export a class/interface from a service and call from a client (local system service)? – sarat Mar 01 '12 at 08:03
  • @sarat, take a look at my response here: http://stackoverflow.com/questions/1773046/gui-and-windows-service-communication/1774642#1774642 – Matt Davis Mar 01 '12 at 14:15
  • 3
    `System.UnauthorizedAccessException: Access to the path 'C:\MyService.InstallState' is denied.` Turns out you have to run *cmd.exe* with: **Run as administrator**. – JohnB Nov 22 '13 at 22:53
  • +1 This worked for me too, especially step 9 for a custom log, where I also made the installer write the first entry. Many other answers to similar questions say to use WiX, but it's not needed with this solution. Much more helpful than MSDN, and requires admin rights only during install time. – Bratch Jun 18 '14 at 17:27
  • The Service1 component has some collapsed source code, so it's not intuitive to reset the name of Service1. Expand Service1.cs > Expand Service1.Designer.cs > Expand code block "Component Designer generated code" > Update this.ServiceName = "Service1" – MacGyver Nov 25 '15 at 16:52
  • @MattDavis Where can I view the custom event logs "ServiceExample" once I install the service? – indusBull Feb 15 '16 at 20:59
  • @indusBull, use the Windows event viewer. From the Start menu, search "eventvwr." Then look for it under Applications and Services Logs. – Matt Davis Feb 16 '16 at 16:06
  • I know it's old, and thank you, @Matt-Davis, for your excellent explanation (+1), but I just thought I'd add that you can make a 1-liner out of the FindInstaller() method. If you include `using System.Linq;`, you can just say in ProjectInstaller(): `EventLogInstaller installer = this.Installers.Cast().FirstOrDefault( eli => eli is EventLogInstaller ) as EventLogInstaller; if( installer != null ) installer.Log = "ServiceExample";` Just my two cents. – Meloviz Feb 23 '16 at 21:01
4

I agree with everyone that has responded elsewhere, but I would say don't focus too much on the actual language, as long as you're working in the .NET framework, and there's a starter project for you, you're good to go. I've done several "Windows services" in the past, and developed them both in VB.NET and C#, with minimal code.

What I would recommend the OP to do is to learn how to build the installer package for it. Installing the service is as easy as executing "installutil.exe {drive}\path\to\file.exe", but when you have to do anything larger than deploying a "hello world" Windows service, it's good to know and understand how do deploy the service in a meaningful way.

Not to start a flame war, but I've "standardized" on using WiX for all my deployment packages, outside of doing old-school COM interop type stuff, since that's a brunt of work to get to install correctly. I'm anxious for the WiX team to develop the bootstrapper piece that allows you to put the prerequisites and the main msi into an EXE file which can be downloaded. They have it slated for 3.5, so I'll patiently wait, and use WinZip Self-Extracting executables for now.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Richard B
  • 1,581
  • 1
  • 15
  • 30
  • 1
    Wow! this is an old post. I wound up learning how to use Heat.exe and extract the bits i needed to use WiX with libs that were com interop enabled. – Richard B Dec 19 '13 at 22:40
0

For me, and I've only tried it a couple of ways, Visual Studio and C# was the easiest.

Visual Studio did all of the necessary service plumbing setup for the framework and I found C# very easy to learn, migrating from VB6, VB.NET and C.

Doug L.
  • 2,616
  • 1
  • 18
  • 32
0

With Visual C#, you'll find the most code samples on the net. Combined with Visual Studio, and it's a walk in the park to get a basic Windows Service up and running. Visual Studio also makes it a snap to create a MSI installer package.

That would be my pick

Scott Ferguson
  • 7,290
  • 7
  • 34
  • 64
0

Use the Visual Studio Service type project, use C# or VB.NET.

I personally prefer C#, but in general it's easy to understand the life cycle and code the logic at the desired stage.

Building an installer is also very easy.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Novice
  • 833
  • 1
  • 10
  • 20
0

A windows service project in C# will give you a fully deployable service from the Visual Studio template with the click of a button. You just need to add your payload code.

cdonner
  • 34,608
  • 21
  • 96
  • 146