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

Start/Stop Windows Services from XML Lists

0.00/5 (No votes)
27 Jun 2014 1  
Stop unneeded Windows services to free memory

Introduction

My laptop has only 8GB of memory. When SQL Server 2012 Services are running, it isn't possible for me to run either a 4.5GB DataRam Ramdrive (hosting Accuzip USPS postal data) or a 4GB Oracle VM Virtual Box (hosting Windows 8.1x64 and VS "2014" CTP). Instead of manually running SQL Server Configuration Manager and trying to remember what services to start or stop, I wrote a WPF MVVM app to start or stop services based on an XML list.

Background

using System.ServiceProcess.ServiceController

Using the Code

If all the services in the list are stopped, the "Stop" button is disabled.

If all the services in the list are running, the "Start" button is disabled.

To configure for running, change the app.config "xmlPath" user setting to the XML list files path and edit in your SQL Server Name - mine is "MCO" - in StartStopSqlServer.xml.

The XML list file is read into a List<service>.

class service
{
    internal string name;
    internal TimeSpan startTimeout, stopTimeout;
    internal bool stopOnly;
    internal static int DefaultStopMs, DefaultStartMs;
    internal service(string name, int stopMs, int startMs, bool stopOnly)
    {
        this.name = name;
        stopMs = (stopMs > 0) ? stopMs : DefaultStopMs;
        startMs = (startMs > 0) ? startMs : DefaultStartMs;
        stopTimeout = new TimeSpan(0, 0, 0, 0, stopMs);
        startTimeout = new TimeSpan(0, 0, 0, 0, startMs);
        this.stopOnly = stopOnly;
    }    
}
List<service> ssServices = null;

    App.Messenger.Register<string>("InitializeViewModel", (xmlFn) =>
        {
            Status = "Loading";
            using (XmlTextReader xmlReader = new XmlTextReader(xmlFn))
            {
                XDocument xdoc = XDocument.Load(xmlReader);
                service.DefaultStopMs = Convert.ToInt32(xdoc.Root.Attribute
                ("DefaultStopMs") !=null ? xdoc.Root.Attribute
                ("DefaultStopMs").Value : "100" );
                service.DefaultStartMs = Convert.ToInt32(xdoc.Root.Attribute
                ("DefaultStartMs") != null ? xdoc.Root.Attribute
                ("DefaultStartMs").Value : "100");
                var services = from serviceItem in xdoc.Root.Elements()
                               select new service(
                                   serviceItem.Value,
                                   Convert.ToInt32(serviceItem.Attribute("StopMs") != null ? 
                                   serviceItem.Attribute("StopMs").Value : "-1"),
                                   Convert.ToInt32(serviceItem.Attribute("StartMs") != null ? 
                                   serviceItem.Attribute("StartMs").Value : "-1"),
                                   Convert.ToBoolean(serviceItem.Attribute("StopOnly") != null ? 
                                   serviceItem.Attribute("StopOnly").Value : "false")
                                   );
                ssServices = services.ToList();
                L = ssServices.Count;
                WindowHeight = 150;
                Status = "Loaded";
            }
        });
    System.Windows.Input.CommandManager.InvalidateRequerySuggested();
}

// The services are start/stopped in the background worker

    backgroundWorker.DoWork += (s, e) =>
        {
            BackgroundWorker bw = (s as BackgroundWorker);
            stop = (e.Argument as bool?).HasValue ? (e.Argument as bool?).Value : true;
            foreach (service se in ssServices)
            {
                if (!stop && se.stopOnly)
                {
                    sleep(displaySleepMS);
                    continue;
                }
            string exceptionMessage = null;
            bool acted = false;
            ServiceController sc = new ServiceController(se.name);
            ServiceControllerStatus scs = ServiceControllerStatus.Stopped;
            try
            {
                scs = sc.Status;
            }
            catch(Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
            if (scs == (stop ? ServiceControllerStatus.Running : ServiceControllerStatus.Stopped))
            {
                App.Messenger.NotifyColleagues("setStatus", 
                (stop ? "Stopping " : "Starting ") + se.name);
                for (int retry = 0; retry < maxRetries; retry++)
                {
                    try
                    {
                        if (retry > 0)
                            sc = new ServiceController(se.name);
                        if (sc.Status == (stop ? ServiceControllerStatus.Running : ServiceControllerStatus.Stopped))
                            if (stop)
                                sc.Stop();
                            else
                                sc.Start();
                        sc.WaitForStatus(
                            stop ? ServiceControllerStatus.Stopped : ServiceControllerStatus.Running,
                            se.startTimeout);
                        acted = true;
                        actedCount++;
                        break;
                    }
                    catch (Exception ex)
                    {
                        if (retry == maxRetries - 1)
                            exceptionMessage = ex.Message;
                        else
                            sleep(1000);
                    }
                }
            }
            if (exceptionMessage != null)
                App.Messenger.NotifyColleagues("setStatus", 
                se.name + (stop ? " Stop" : " Start")
                    + " Failed: " + exceptionMessage);
            else
                if (acted)
                    App.Messenger.NotifyColleagues("setStatus", 
                    se.name + (stop ? " Stopped" : " Started"));
                else
                    App.Messenger.NotifyColleagues("setStatus", 
                    se.name + " Already" + (stop ? " Stopped" : " Started"));
                    
            sleep(displaySleepMS);
            if (bw.CancellationPending)
            {
                e.Cancel = true;
                break;
            }
        }
        bw.ReportProgress(L);
        sleep(displaySleepMS);
        if (e.Cancel)
            e.Result = "Cancelled";
        else
            e.Result = (stop ? "Stopped " : "Started ") + 
            actedCount.ToString() + " Services"; 
        };

Points of Interest

SQL Server services XML is as follows:

<?xml version="1.0"?>
<Services DefaultStopMs="3000" DefaultStartMs="10000" Type="Sql Server Type">
  <Service StopMs="4000" StartMs="12000">MSSQL$MCO</Service>
  <!--
    Not using
  <Service>MSSQL$SQLEX</Service>
  <Service>MSSQL$SQLEXPRESS</Service>
  -->
  <Service>MSOLAP$MCO</Service>
  <Service>SQLBrowser</Service>
  <Service>MsDtsServer110</Service>
  <Service>SQLWriter</Service>
  <Service>ReportServer$MCO</Service>
  <!-- MSSQLFDLauncher is autostarted by MSSQLSERVER
       when stopping MSSQLSERVER must be stopped before 
       MSSQLFDLauncher, when starting skip MSSQLFDLauncher
  -->
  <Service StopOnly="true">MSSQLFDLauncher$MCO</Service>
  <!--
    Not using
  <Service>SQLAGENT$MCO</Service>
  -->
</Services>

I also included "StartStopAmazonServices.xml" to stop Amazon services.

<?xml version="1.0" encoding="utf-8"?>
<Services Type="Amazon Unbox">
  >

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