Wi-Fi Detector Shirt
Labels: Information, Internet, Misc
Control and List Windows Services
As I whipped up my file synchronizing service application, to synchronize files between my computer and my NAS), I worked with the System.ServiceProcess Namespace. The System.ServiceProcess Namespace "provides classes that allow you to implement, install, and control Windows service applications".
My file synchronization needs did not require that my application service to be "running" all the time. In, fact I only needed the service to run under certain situations. It was easy enough to get the service written and installed and now I wanted to 'automatically' (programmatically) start and stop my service when certain conditions were met.
Entrance - the ServiceController Class. The ServiceController Class "Represents a Windows service and allows you to connect to a running or stopped service, manipulate it, or get information about it." In order to get acclimated to the ServiceController Class I created a simple application to list and display information about the installed services.
using System;
using System.Windows.Forms;
using System.ServiceProcess;
namespace Services1
...{
public partial class Form1 : Form
...{
ServiceController controller;
public Form1()
...{
controller = new ServiceController();
controller.MachineName = ".";
InitializeComponent();
lstServices.DisplayMember = "DisplayName";
lstServices.ValueMember = "ServiceName";
lstServices.DataSource = ServiceController.GetServices();
}
private void StartService(string servicename)
...{
controller.ServiceName = servicename;
controller.Start();
}
private void PauseService(string servicename)
...{
controller.ServiceName = servicename;
if (controller.CanPauseAndContinue)
controller.Pause();
}
private void StopService(string servicename)
...{
controller.ServiceName = servicename;
if (controller.CanStop)
controller.Stop();
}

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
...{
if (lstServices.SelectedItems.Count > 0)
...{
try
...{
controller.ServiceName = lstServices.SelectedValue.ToString();
textBox1.Text = String.Format(
"Service Name: {0}\r\nDisplay Name: {1}\r\nType: {2}\r\nStatus: {3}",
controller.ServiceName,
controller.DisplayName,
controller.ServiceType.ToString(),
controller.Status.ToString()
);
}
catch (Exception ex)
...{
textBox1.Text = String.Format("Error: \r\n{0}",ex.Message);
}
}
else
...{
textBox1.Clear();
}
}
private void btnStart_Click(object sender, EventArgs e)
...{
StartService(lstServices.SelectedValue.ToString());
}
private void btnPause_Click(object sender, EventArgs e)
...{
PauseService(lstServices.SelectedValue.ToString());
}
private void btnStop_Click(object sender, EventArgs e)
...{
StopService(lstServices.SelectedValue.ToString());
}
}
}
Let's Synchronize Some FilesRecently, I posted about the new addition to my backup strategy; a NAS. My intended use of this device is to have a hot backup of my files. The system I was using before was not capable of storing the amount of data I need backed up, nor was it easy to manage.
I modified the set of xCopy batch files that I used for my backups to write the files to the NAS.
This system worked fine, but I needed more. I manage a lot of data and have a lot of files. I wouldn't want to lose any in the event of a system failure. The one problem I see with using this process is the lack of a real time solution.
I was in search of a solution that would offer me real-time synchronization between my files and the NAS. I didn't have to search very far. The .NET Framework includes the FileSystemWatcher Class.
The FileSystemWatcher Class "Listens to the file system change notifications and raises events when a directory, or file in a directory, changes." (quoted directly from MSDN) After reading through this class I quickly whipped up a solution. I developed my own FileSync class that allowed me to easily synchronize files between my remote and local storage. I created a Windows Service (threaded) built around my class (the screen shot in this post is from a sample app I used to test my class) so that I could have the FileSync class running and keeping my files in sync without me needing to do anything. Here is the unit I created:
using System;
using System.IO;
using System.Diagnostics;
namespace BPSoftware
...{
class FileSync
...{
private FileSystemWatcher watcher;

Fields#region Fields
private string destpath;
public string DestPath
...{
get ...{ return destpath; }
set ...{ destpath = value; }
}
private string sourcepath;
public string SourcePath
...{
get ...{ return sourcepath; }
set ...{ sourcepath = value; }
}
private string filter;
public string Filter
...{
get ...{ return filter; }
set ...{ filter = value; }
}
private bool watchsubfolders;
public bool WatchSubFolders
...{
get ...{ return watchsubfolders; }
set ...{ watchsubfolders = value; }
}
#endregion

Constructors#region Constructors
public FileSync()
...{
this.watcher = new FileSystemWatcher();
this.watcher.InternalBufferSize = 0x20000;
this.watcher.NotifyFilter = NotifyFilters.FileNameNotifyFilters.LastWrite;
this.watcher.IncludeSubdirectories = false;
this.watcher.Changed += new FileSystemEventHandler(this.OnChanged);
this.watcher.Created += new FileSystemEventHandler(this.OnCreated);
this.watcher.Deleted += new FileSystemEventHandler(this.OnDeleted);
this.watcher.Renamed += new RenamedEventHandler(this.OnRenamed);
}
public FileSync(string source, string destination, string filefilter, bool watchsubs): this()
...{
this.SourcePath = source;
this.DestPath = destination;
this.Filter = filefilter;
this.WatchSubFolders = watchsubs;
}
#endregion

Methods#region Methods
private string GetDestinationFile(string infile)
...{
string fileName = Path.GetFileName(infile);
return (this.destpath + fileName);
}
private void LogEvent(string message, int id)
...{
EventLog.WriteEntry("FileSync", message, EventLogEntryType.Error, id);
}
public void Start()
...{
try
...{
if (this.watcher != null)
...{
this.watcher.Path = this.SourcePath;
this.watcher.Filter = this.Filter;
this.watcher.IncludeSubdirectories = this.WatchSubFolders;
this.watcher.Filter = this.Filter;
this.watcher.EnableRaisingEvents = true;
}
}
catch (Exception exception)
...{
this.LogEvent(exception.Message, 0x01);
}
}
public bool Stop()
...{
try
...{
if (this.watcher != null)
...{
this.watcher.EnableRaisingEvents = false;
this.watcher.Changed -= new FileSystemEventHandler(this.OnChanged);
this.watcher.Created -= new FileSystemEventHandler(this.OnCreated);
this.watcher.Deleted -= new FileSystemEventHandler(this.OnDeleted);
this.watcher.Renamed -= new RenamedEventHandler(this.OnRenamed);
}
}
catch (Exception exception)
...{
this.LogEvent(exception.Message, 0x02);
return false;
}
return true;
}
#endregion

Events#region Events
private void OnChanged(object source, FileSystemEventArgs e)
...{
try
...{
File.Copy(e.FullPath, this.GetDestinationFile(e.FullPath), true);
}
catch (Exception exception)
...{
this.LogEvent(exception.Message, 0x03);
}
}
private void OnCreated(object source, FileSystemEventArgs e)