Introduction
Controlling services from code has never been so easy. The .NET framework has taken the cumbersome task of wrapping the Windows API calls that we traditionally used to control services.
Using the code
First, let's get a list of services running on the machine. To do this, we will call the static method GetServices()
of the System.ServiceProcess.ServiceController
class.
System.ServiceProcess.ServiceController[] services;
services = System.ServiceProcess.ServiceController.GetServices();
In my application, I load a ComboBox
with the list of services running on the machine. To make life easy, I create a DataTable
on the fly and add records to it to represent the individual services. Then I bind the DataTable
that I created to the ComboBox
. I also take some additional steps to sort the data in the DataTable
and to add an initial ComboBox
entry that prompts the user to "Select A Service".
_tblServices.Columns.Add( new DataColumn( "ServiceName", typeof( System.String ) ));
_tblServices.Columns.Add( new DataColumn( "DisplayName", typeof( System.String ) ));
_tblServices.Columns.Add( new DataColumn( "Index",
typeof( System.Int32 ) ));
System.ServiceProcess.ServiceController[] services;
services = System.ServiceProcess.ServiceController.GetServices();
foreach( System.ServiceProcess.ServiceController controller in services )
{
DataRow row = _tblServices.NewRow();
row["ServiceName"] = controller.ServiceName;
row["DisplayName"] = controller.DisplayName;
row["Index"] = 1;
_tblServices.Rows.Add( row );
}
DataRow blankRow = _tblServices.NewRow();
blankRow["ServiceName"] = string.Empty;
blankRow["DisplayName"] = "<Select A Service>";
blankRow["Index"] = 0;
_tblServices.Rows.Add( blankRow );
DataView view = new DataView( _tblServices, string.Empty,
"Index, DisplayName",
DataViewRowState.CurrentRows );
cbServices.DataSource = view;
cbServices.ValueMember = "ServiceName";
cbServices.DisplayMember = "DisplayName";
cbServices.SelectedValueChanged +=
new EventHandler(cbServices_SelectedValueChanged);
In the previous code, the ComboBox
was assigned an event handler. The SelectedValueChanged
event will allow me to update the GUI according to the status of the selected service. In order to get the status of the service I instantiate a new ServiceController
object and pass in the Service Name. Then I enable/disable each button depending on the current service status.
private void cbServices_SelectedValueChanged(object sender, System.EventArgs e)
{
ServiceController controller = GetService();
if( controller != null )
UpdateControls( GetService() );
else
{
statusBar1.Text = string.Empty;
btnStart.Enabled = false;
btnStop.Enabled = false;
btnPause.Enabled = false;
btnContinue.Enabled = false;
}
}
void UpdateControls( ServiceController controller )
{
btnPause.Enabled = ( controller.Status == ServiceControllerStatus.Running
&& controller.CanPauseAndContinue == true );
btnStop.Enabled = ( controller.Status == ServiceControllerStatus.Running
&& controller.CanStop == true );
btnContinue.Enabled = ( controller.Status == ServiceControllerStatus.Paused
&& controller.CanPauseAndContinue == true );
btnStart.Enabled = controller.Status == ServiceControllerStatus.Stopped;
statusBar1.Text = "Status: " + controller.Status.ToString();
}
private ServiceController GetService()
{
if( cbServices.SelectedValue.ToString().Trim() != string.Empty )
return new ServiceController( (string)cbServices.SelectedValue );
else
return null;
}
If you are familiar with services you are probably aware that some services can not be stopped or paused. This can be checked by accessing the CanPauseAndContinue
property and the CanStop
property of the ServiceController
class. Since my UpdateControls()
method checks these properties I don't have to check these properties again during the button Click
events.
private void btnStop_Click(object sender, System.EventArgs e)
{
System.ServiceProcess.ServiceController controller = GetService();
controller.Stop();
WaitForStatus( controller, ServiceControllerStatus.Stopped,
new TimeSpan( 0,1,0) );
UpdateControls( controller );
}
private void btnStart_Click(object sender, System.EventArgs e)
{
System.ServiceProcess.ServiceController controller = GetService();
controller.Start();
WaitForStatus( controller, ServiceControllerStatus.Running,
new TimeSpan( 0,1,0) );
UpdateControls( controller );
}
private void btnPause_Click(object sender, System.EventArgs e)
{
System.ServiceProcess.ServiceController controller = GetService();
controller.Pause();
WaitForStatus( controller, ServiceControllerStatus.Paused,
new TimeSpan( 0,1,0) );
UpdateControls( controller );
}
private void btnContinue_Click(object sender, System.EventArgs e)
{
System.ServiceProcess.ServiceController controller = GetService();
controller.Continue();
WaitForStatus( controller, ServiceControllerStatus.Running,
new TimeSpan( 0,1,0) );
UpdateControls( controller );
}