Windows Service -- Part 1: Creating Windows Service

Summary
Through out this series of tutorials we'll learn how to create a Windows service project in C#, how to install it, how to debug an installed Windows service and how control a windows service from an application. This is a three series tutorials on Windows service. In the first part we'll learn how to create a 'Windows Service Project'. In the second part we'll learn how to install the service and how to debug it. In the last part we'll learn how to control a service from another client application. Here 'controlling a service' means starting, stopping, sending commands to a service.



The job of the service will be to monitor the directory of the service's exe for any file/folder creation during the service running. The service will keep a list of paths of items (file/folder) that will be created in the service's exe directory.


What is Windows Service?
Quoting from WIKI page -- "On Microsoft Windows operating systems, a Windows service is a long-running executable that performs specific functions and it is designed not to require user intervention. Windows services can be configured to start when the operating system is booted and run in the background as long as Windows is running, or they can be started manually when required. They are similar in concept to a Unix daemon. Many appear in the processes list in the Windows Task Manager, most often with a username of SYSTEM, LOCAL SERVICE or NETWORK SERVICE, though not all processes with the SYSTEM username are services. The remaining services run through svchost.exe as DLLs loaded into memory.".


Creating Windows Service Project
  • Open Visual Studio (I'm working with VS2008 but it is same for VS2005 and 2010)
  • Click File-->New Project. 'New Project' wizard will appear on you.
  • Select 'Visual C#-->Windows' from the 'Project Types' options (left side on the wizard)
  • Select 'Windows Service' template from the 'Templates' options (right side on the wizard)
  • Give a name to our project -- let us name it 'CodeCallService'. And click on Ok button.Attached File  create_project.PNG   36.37K   11 downloads
  • A project named 'CodeCallService' will be created. In the 'Solution Explorer', you'll see that a component of named Service1.cs (inherited from ServiceBase class) is created. Rename it to FileWatcherService.cs.
  • To change the service name that will be shown in the 'Windows Service Control Manager' double click the 'FileWatcherService.cs' component on the 'Solution Explorer'. The component will be viewed in designer mode. Right click --> Properties on the designer (or press F4) to open the 'Properties page' dock panel for the service componentAttached File  Change_propoerites.PNG   50.67K   15 downloads. The name default name is 'Service1'. Let us change it to 'CCFSWatcher' (the ServiceName property). Let us also set the 'CanPauseAndConituee' property to 'True'.
By default the onstart and onstop methods are created in class FileWatcherService class for us by the project template. The onstart method is called when this service will be started -- may be when system boots (if the service start mode is set to automatically) or when user manually start it from the 'Windows Service Manager'.  The onstop method is called when this service will be stopped-- may be when system shutdown or when user manually stop it from the 'Windows Service Manager'. As we set 'CanPauseAndConituee' property to 'True', our service will also get notified when the service gets paused or when resume. So we can override the 'onpause' and 'OnConitnue' methods in our FileWatcherServiceclass.  Following is the empty code structure of the class 'FileWatcherService'
namespace CodeCallService
{
public partial class FileWatcherService: ServiceBase
{
public FileWatcherService()
{
InitializeComponent
();
}
protected override void onstart(string[] args)
{
// Gets called when this service starts
base.onstart(args);
}
protected override void onpause()
{
// Gets called when this service pause
base.onpause();
}
protected override void OnContinue()
{
// Gets called when this service resume running
base.OnContinue();
}
protected override void onstop()
{
// Gets called when this service stopped
base.onstop();
}
}
}
We can also use some other properties to handle some special events...
  • CanHandlePowerEvent: If we set this to true and override the 'bool OnPowerEvent(PowerBroadcastStatus powerStatus)' method, we'll get a notification of power status changed event in the system. This is useful for detecting laptop's batter state change event.
  • CanHandleSessionchangeEvent: If we set this to true and override 'void OnSessionchange(SessionchangeDescription changeDescription)' method, we'll get notification about sessions received from a Terminal Server session. As example, we'll get notification when we locked/unlocked computer, log on/off, Remote control, Remote connect/disconnect and others. See a complete list of session change reason here at msdn.
  • CanShutdown: If we set this to true and override 'void OnShutdown()' method, we'll get notification in our service in case of system shutdown.


Adding the FileSystemWatcher Component 
To add a 'FileSystemWatcher' component to our service, follow the steps.
  • To open the our service component in designer, double click the 'FileWatcherService.cs' it.
  • Drag the 'FileSystemWatcher' component from the ToolBox dock-panel to the designer.Attached File  create_fsw.PNG   54.56K   22 downloads. To learn more about FileSystemWatcher  read on MSDN here.
  • A FileSystemWatcher component will be added in the 'FileWatcherService' class with the default name fileSystemWatcher1'. Let us rename it to '_fsWatcher' from the property page. Also set the 'EnableRaisingEvents' true false and 'IncludeSubdirectories' to true.Attached File  fsw_prop.PNG   50.42K   22 downloads
  • Now we need to handle 'Created' event of FileSystemWatcher component. Select the properties page, click the 'Events' button, double click on the 'Created' event. Attached File  fsw_event.PNG   53.25K   16 downloads The '_fsWatcher_Created' event handler will be created in the class 'FileSystemWatcher'.


The File Watcher Logic Part
The logic is simple. We'll create our li
st in the constructor. We'll also set the FileSysemWatcher monitoring path in the constructor. We will just need to set the 'EnableRaisingEvents' to 'true' in the onstart and OnContinue method and to 'false' in the onstop and onpause method. We'll also clear our items list in the onstop method. The '_fsWatcher_Created' will be called by the system when a an item (file/folder) is created. We need to just the add the FullPath of the item in the list. Here is the full-code.

namespace CodeCallService
{
public partial class FileWatcherService : ServiceBase
{
List<String> _createdItems;
public FileWatcherService()
{
InitializeComponent();

_createdItems
= new List<string>();
_fsWatcher
.Path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
}
protected override void onstart(string[] args)
{
// Gets called when this service starts
base.onstart(args);
_fsWatcher
.EnableRaisingEvents = true;
}
protected override void onpause()
{
// Gets called when this service pause
_fsWatcher
.EnableRaisingEvents = false;
base.onpause();
}
protected override void OnContinue()
{
// Gets called when this service resume running
base.OnContinue();
_fsWatcher
.EnableRaisingEvents = true;
}
protected override void onstop()
{
// Gets called when this service stopped
_fsWatcher
.EnableRaisingEvents = false;
_createdItems
.Clear();
base.onstop();
}
private void _fsWatcher_Created(object sender, System.IO.FileSystemEventArgs e)
{
_createdItems
.Add(e.FullPath);
}
}
}

That's all for this part. Back soon with the next part. :)

No comments:

Post a Comment