Search This Blog

Install the Windows Service

Windows Services are different than normal Windows based applications. It is not possible to run a Windows Service by simply running an EXE. The Windows Service should be installed by using the InstallUtil.exe provided with the .NET Framework or through a deployment project such as a Microsoft Installer (MSI) file.

Add an Installer
Having created the Windows Service will not be enough for the InstallUtil program to be able to install the service. You must also add an Installer to your Windows Service so that the InstallUtil, or any other installation program, knows what configuration settings to apply to your service.

Switch to the design view for the service
Right click and select Add Installer
Switch to the design view of the ProjectInstaller that is added
Set the properties of the serviceInstaller1 component
ServiceName = My Sample Service
StartType = Automatic
Set the properties of the serviceProcessInstaller1 component
Account = LocalSystem
Build the Solution
The following code contained in the ProjectInstaller.cs source file was automatically generated by Visual Studio after having completed the steps above.

using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;

namespace CodeGuru.MyWindowsService
{
///
/// Summary description for ProjectInstaller.
///

[RunInstaller(true)]
public class ProjectInstaller :
System.Configuration.Install.Installer
{
private System.ServiceProcess.ServiceProcessInstaller
serviceProcessInstaller1;
private System.ServiceProcess.ServiceInstaller serviceInstaller1;
///
/// Required designer variable.
///

private System.ComponentModel.Container components = null;

public ProjectInstaller()
{
// This call is required by the Designer.
InitializeComponent();

// TODO: Add any initialization after the InitComponent call
}

#region Component Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///

private void InitializeComponent()
{
this.serviceProcessInstaller1 = new
System.ServiceProcess.ServiceProcessInstaller();
this.serviceInstaller1 = new
System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller1
//
this.serviceProcessInstaller1.Account =
System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
//
// serviceInstaller1
//
this.serviceInstaller1.ServiceName = "My Sample Service";
this.serviceInstaller1.StartType =
System.ServiceProcess.ServiceStartMode.Automatic;
//
// ProjectInstaller
//
this.Installers.AddRange(new
System.Configuration.Install.Installer[]
{this.serviceProcessInstaller1, this.serviceInstaller1});
}
#endregion
}
}

Use InstallUtil to Install the Windows Service

The following instructions will guide you in installing your new service.

Open a Visual Studio .NET Command Prompt
Change to the bin\Debug directory of your project location (bin\Release if you compiled in release mode)
Issue the command InstallUtil.exe MyWindowsService.exe to register the service and have it create the appropriate registry entries
Open the Computer Management console by right clicking on My Computer on the desktop and selecting Manage
In the Services section underneath Services and Applications you should now see your Windows Service included in the list of services
Start your service by right clicking on it and selecting Start
Each time you need to change your Windows Service it will require you to uninstall and reinstall the service. Prior to uninstalling the service it is a good idea to make sure you have the Services management console closed. If you do not you may have difficulty uninstalling and reinstalling the Windows Service. To uninstall the service simply reissue the same InstallUtil command used to register the service and add the /u command switch.

Debug the Windows Service

As with all other aspects, debugging a Windows Service is different than a normal application. More steps are required to debug a Windows Service. The service cannot be debugged by simply executing it in the development environment as you can with a normal application. The service must first be installed and started, which we covered in the previous section. Once it is started you attach Visual Studio to the running process in order to step through and debug the code. Remember, each change you make to the Windows Service will require you to uninstall and reinstall the service.

Attach to a Running Windows Service

Here are the directions for attaching to a Windows Service in order to debug the application. These instructions assume that you have already installed the Windows Service and it is currently running.

Load the project into Visual Studio
Click on the Debug menu
Click on the Processes menu item
Make sure the Show system processes is selected
Locate your process in the Available Processes list based on the name of your executable and click on it
Click the Attach button
Click OK
Click Close
Set a break point in the timer1_Elapsed method and wait for it to execute

Windows service Interact with Desktop- Display GUI

using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
using Microsoft.Win32;
using System.Management;


using System.Diagnostics;
namespace Service1
{
///
/// Summary description for ProjectInstaller.
///

[RunInstaller(true)]
public class ProjectInstaller : System.Configuration.Install.Installer
{
///
/// Required designer variable.
///

private System.ComponentModel.Container components = null;
private string SerName = "service1";
public ProjectInstaller()
{
// This call is required by the Designer.
InitializeComponent();

// TODO: Add any initialization after the InitComponent call





ServiceInstaller si = new ServiceInstaller();
si.ServiceName = SerName;
si.DisplayName = SerName;
si.Description = "services1";
si.AfterInstall += new InstallEventHandler(si_AfterInstall);



si.StartType = ServiceStartMode.Manual;
Installers.Add(si);
ServiceProcessInstaller spi = new ServiceProcessInstaller();
spi.Account = System.ServiceProcess.ServiceAccount.LocalSystem;


spi.Password = null;
spi.Username = null;
Installers.Add(spi);

}

#region Component Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///

private void InitializeComponent()
{
//
// ProjectInstaller
//
this.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.ProjectInstaller_AfterInstall);

}
#endregion

private void si_AfterInstall(object sender, System.Configuration.Install.InstallEventArgs e)
{
ConnectionOptions coOptions = new ConnectionOptions();
coOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope mgmtScope = new System.Management.ManagementScope(@"root\CIMV2", coOptions);
mgmtScope.Connect();
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" + SerName + "'");
ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
InParam["DesktopInteract"] = true; ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
}





}
}

Stop Windows Service -C# code

. System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController();
sc.ServiceName = "ServiceName";
if (sc.Status == System.ServiceProcess.ServiceControllerStatus.Running)
{
sc.Stop();
}

Start Windows Service -C# code

ServiceController sc = new ServiceController();
sc.ServiceName = "ServiceName1";
if (sc.Status == ServiceControllerStatus.Stopped)
{
sc.Start();
}

Create/Install Windows Service -c# code


hit tracker

Create Windows Service

Add the System.ServiceProcess and System.Configuration.Install references to your project. In the Solution Explorer, right-click "References", and select "Add Reference...". In the dialog box that pops up, make sure the ".NET" tab is selected, and then scroll down in the list to "System.ServiceProcess", select it, and click OK. You'll see a new entry under References. This will allow you to write code that references the System.ServiceProcess classes. Repeat the process to add the System.Configuration.Install reference.


Now, add two new class files to the project, one labeled: "WindowsService.cs" and the other: "WindowsServiceInstaller.cs". In the Solution Explorer, right-click the project name and go to: [Add]->[Class]. Name the class "WindowsService.cs" and then hit OK. Repeat the process for "WindowsServiceInstaller.cs". Now you have two brand-new files with the basics.


In the "WindowsService.cs" class, copy the following:




using System;
using System.Diagnostics;
using System.ServiceProcess;

namespace WindowsService
{
class WindowsService : ServiceBase
{
/// <summary>
/// Public Constructor for WindowsService.
/// - Put all of your Initialization code here.
/// </summary>
public WindowsService()
{
this.ServiceName = "My Windows Service";
this.EventLog.Log = "Application";

// These Flags set whether or not to handle that specific
// type of event. Set to true if you need it, false otherwise.
this.CanHandlePowerEvent = true;
this.CanHandleSessionChangeEvent = true;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.CanStop = true;
}

/// <summary>
/// The Main Thread: This is where your Service is Run.
/// </summary>
static void Main()
{
ServiceBase.Run(new WindowsService());
}

/// <summary>
/// Dispose of objects that need it here.
/// </summary>
/// <param name="disposing">Whether
/// or not disposing is going on.</param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}

/// <summary>
/// OnStart(): Put startup code here
/// - Start threads, get inital data, etc.
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
base.OnStart(args);
}

/// <summary>
/// OnStop(): Put your stop code here
/// - Stop threads, set final data, etc.
/// </summary>
protected override void OnStop()
{
base.OnStop();
}

/// <summary>
/// OnPause: Put your pause code here
/// - Pause working threads, etc.
/// </summary>
protected override void OnPause()
{
base.OnPause();
}

/// <summary>
/// OnContinue(): Put your continue code here
/// - Un-pause working threads, etc.
/// </summary>
protected override void OnContinue()
{
base.OnContinue();
}

/// <summary>
/// OnShutdown(): Called when the System is shutting down
/// - Put code here when you need special handling
/// of code that deals with a system shutdown, such
/// as saving special data before shutdown.
/// </summary>
protected override void OnShutdown()
{
base.OnShutdown();
}

/// <summary>
/// OnCustomCommand(): If you need to send a command to your
/// service without the need for Remoting or Sockets, use
/// this method to do custom methods.
/// </summary>
/// <param name="command">Arbitrary Integer between 128 & 256</param>
protected override void OnCustomCommand(int command)
{
// A custom command can be sent to a service by using this method:
//# int command = 128; //Some Arbitrary number between 128 & 256
//# ServiceController sc = new ServiceController("NameOfService");
//# sc.ExecuteCommand(command);

base.OnCustomCommand(command);
}

/// <summary>
/// OnPowerEvent(): Useful for detecting power status changes,
/// such as going into Suspend mode or Low Battery for laptops.
/// </summary>
/// <param name="powerStatus">The Power Broadcast Status
/// (BatteryLow, Suspend, etc.)</param>
protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
return base.OnPowerEvent(powerStatus);
}

/// <summary>
/// OnSessionChange(): To handle a change event
/// from a Terminal Server session.
/// Useful if you need to determine
/// when a user logs in remotely or logs off,
/// or when someone logs into the console.
/// </summary>
/// <param name="changeDescription">The Session Change
/// Event that occured.</param>
protected override void OnSessionChange(
SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
}
}
}

In the "WindowsServiceInstaller.cs" class, copy the following:

using System;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

namespace WindowsService
{
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
/// <summary>
/// Public Constructor for WindowsServiceInstaller.
/// - Put all of your Initialization code here.
/// </summary>
public WindowsServiceInstaller()
{
ServiceProcessInstaller serviceProcessInstaller =
new ServiceProcessInstaller();
ServiceInstaller serviceInstaller = new ServiceInstaller();

//# Service Account Information
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;

//# Service Information
serviceInstaller.DisplayName = "My New C# Windows Service";
serviceInstaller.StartType = ServiceStartMode.Automatic;

//# This must be identical to the WindowsService.ServiceBase name
//# set in the constructor of WindowsService.cs
serviceInstaller.ServiceName = "My Windows Service";

this.Installers.Add(serviceProcessInstaller);
this.Installers.Add(serviceInstaller);
}
}
}

The ServiceAccount section of the code is important for the security context under which your code will run. For every enumeration except User, set the Username and Password properties to null.


You can set the Account property to the following (this is mostly from Microsoft's help file):



  • The LocalSystem enumeration defines a highly privileged account, but most services do not require such an elevated privilege level.
  • The LocalService enumeration provides a lower privilege level for the security context.
  • The NetworkService enumeration provides extensive local privileges, and provides the computer's credentials to remote servers.
  • The User enumeration allows the use of a username and password combination to set the privilege level for the security context to that of a specified user.

There. That wasn't so tough! Now, in the WindowsService class, depending on what you're creating this service for, you'll probably want to include a background working thread to handle, well, the work. I've used this code simply by leaving everything as-is with just the OnCustomCommand method modified, and it works OK. If you wish to handle constant or timed processing, best add at least one working thread.


That's as far as I'll go in this article on setting up a Windows Service: everything else is pretty much up to the programmer. Now, the easy/hard part: Installation.


Installation


To install a service, you could create an installation program that encapsulates the executable for deployment, which I find time consuming and inefficient when testing an application. Or, you could install the service though the InstallUtil.exe process that comes with the .NET Framework.


I created a simple batch file, install.bat, to simplify installation (and therefore testing) of the service. The batch script is shown below; uninstallation is as simple as creating another batch file, uninstall.bat, with exactly the same script, only substituting the /i (for install) with /u (for uninstall).

@ECHO OFF

REM The following directory is for .NET 2.0
set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727
set PATH=%PATH%;%DOTNETFX2%

echo Installing WindowsService...
echo ---------------------------------------------------
InstallUtil /i WindowsService.exe
echo ---------------------------------------------------
echo Done.