Development Environment
Operating System: Windows 10 X64
Development Environment: Visual Studio 2015
Programming Languaeg: C#
.NET Version: .NET Framework 4.0
Target Platform: X86
Creating the Windows Service
Create a new Windows Service project named "CustomWindowsService". Rename Service1.cs to MainService.cs and open the code editor.
using System;
using System.IO;
using System.ServiceProcess;
namespace CustomWindowsService
{
public partial class MainService : ServiceBase
{
private readonly string logPath = @"C:\ServiceLog.txt";
public MainService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WriteToLog($"{DateTime.Now}: Service started.");
}
protected override void OnStop()
{
WriteToLog($"{DateTime.Now}: Service stopped.");
}
private void WriteToLog(string message)
{
using (var file = new StreamWriter(logPath, true))
{
file.WriteLine(message);
}
}
}
}
Right-click the design surface and select "Add Installer". Two components will appear: serviceInstaller1 and serviceProcessInstaller1.
Set serviceInstaller1 properties: ServiceName = "MainService", Description = "Custom logging service", StartType = Manual.
Set serviceProcessInstaller1 Account properyt to LocalSystem. Build the project.
Creating a Service Management Interface
Add a Windows Forms project named ServiceManager to the solution. Add four buttons: Install, Start, Stop, and Uninstall.
using System;
using System.Collections;
using System.ServiceProcess;
using System.Configuration.Install;
using System.Windows.Forms;
namespace ServiceManager
{
public partial class ServiceControlForm : Form
{
private const string ServiceName = "MainService";
private readonly string executablePath = $"{Application.StartupPath}\\CustomWindowsService.exe";
private void InstallButton_Click(object sender, EventArgs e)
{
if (ServiceExists(ServiceName)) RemoveService();
InstallService();
}
private void StartButton_Click(object sender, EventArgs e)
{
if (ServiceExists(ServiceName)) StartService();
}
private void StopButton_Click(object sender, EventArgs e)
{
if (ServiceExists(ServiceName)) StopService();
}
private void UninstallButton_Click(object sender, EventArgs e)
{
if (ServiceExists(ServiceName))
{
StopService();
RemoveService();
}
}
private bool ServiceExists(string name)
{
foreach (ServiceController controller in ServiceController.GetServices())
{
if (controller.ServiceName.Equals(name, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
private void InstallService()
{
using (var installer = new AssemblyInstaller())
{
installer.UseNewContext = true;
installer.Path = executablePath;
IDictionary state = new Hashtable();
installer.Install(state);
installer.Commit(state);
}
}
private void RemoveService()
{
using (var installer = new AssemblyInstaller())
{
installer.UseNewContext = true;
installer.Path = executablePath;
installer.Uninstall(null);
}
}
private void StartService()
{
using (var controller = new ServiceController(ServiceName))
{
if (controller.Status == ServiceControllerStatus.Stopped)
controller.Start();
}
}
private void StopService()
{
using (var controller = new ServiceController(ServiceName))
{
if (controller.Status == ServiceControllerStatus.Running)
controller.Stop();
}
}
}
}
Add an application manifest file to the project and modify the execution level to requireAdministrator. Reference the service executable and run the form with administrator privileges.
Debugging the Service
Set breakpoints in the service code. After installing the service, use Visual Studio's Debug → Attach to Process feature to attach to the service process. Trigger service actions through the management interface to hit breakpoints.