Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Service Controller

0.00/5 (No votes)
29 Sep 2005 1  
How to programmatically control an NT Service.

User Interface

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.

//create an array to hold the list of services

System.ServiceProcess.ServiceController[] services;
//fill the array with the GetServices method

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".

//Add columns to the DataTable

_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 ) )); //used for sorting


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 );
}

//add a dummy row

DataRow blankRow = _tblServices.NewRow();
blankRow["ServiceName"] = string.Empty;
blankRow["DisplayName"] = "<Select A Service>";
blankRow["Index"] = 0;
_tblServices.Rows.Add( blankRow );

//use a DataView to sort the entries. I use the "Index" 

//Column to force my blank record to the top

DataView view = new DataView( _tblServices, string.Empty, 
                    "Index, DisplayName", 
                    DataViewRowState.CurrentRows );
cbServices.DataSource = view;
cbServices.ValueMember = "ServiceName";
cbServices.DisplayMember = "DisplayName";

//Assign an event handler to the selectedValueChanged Event

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;
    }
}

//Updates the buttons according to the currently selected service

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();
}

//Gets the currently selected service

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 );
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here