[ACCEPTED]-How can I programmatically stop/start a windows service on a remote box?-windows-services

Accepted answer
Score: 43

in C#:

var sc = new System.ServiceProcess.ServiceController("MyService", "MyRemoteMachine");
sc.Start();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
sc.Stop();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);

0

Score: 9

You can also do this from a command console 3 using the sc command:

 sc <server> start [service name]
 sc <server> stop [service name]

Use

sc <server> query | find "SERVICE_NAME"

to get a list of 2 service names.

The option <server> has the form \\ServerName

Example

sc \\MyServer stop schedule will 1 stop the Scheduler service.

Score: 5

ServiceController.

You need to have permission to administer 5 the services on the remote box.

As Mehrdad 4 says, you can also use WMI. Both methods 3 work for start and stop, but WMI requires 2 more coding and will give you more access 1 to other resources

Score: 3

If you don't want to code it yourself, PsService by 2 Microsoft/Sysinternals is a command line 1 tool that does what you want.

Score: 2

You can use System.Management APIs (WMI) to control services 3 remotely. WMI is the generic API to do administrative 2 tasks.

For this problem, however, I suggest 1 you to use the easier to use System.ServiceProcess.ServiceController class.

Score: 2

if you need to get the name of the Service:

run 4 this from the command line:

sc query

You will 3 see for example, that SQL Server's service 2 name is 'MSSQL$SQLEXPRESS'.

So to stop the 1 SQL Server service in C#:

        ServiceController controller = new ServiceController();
        controller.MachineName = "Machine1";
        controller.ServiceName = "MSSQL$SQLEXPRESS";

        if(controller.Status == ServiceControllerStatus.Running)
            controller.Stop();

        controller.WaitForStatus(ServiceControllerStatus.Stopped);
Score: 2

I have done like below:

Note:

  1. If you didn't start your service if you are trying to stop it will throw exception.
  2. If you configure these things in your web.config ,configuration related exception will not come. No need to do anything in IIS.

In Web.Config under <configuration>

  <appSettings>
    <add key="ServiceName" value="YourServiceName" />
    <add key="MachineName" value="YourMachineName" />
  </appSettings>
  <system.web>
    <authentication mode="Windows"/>
    <identity impersonate="true" userName="YourUserName" password="YourPassword"/>
  </system.web>

In My Service Class:

private void RestartService()
{
    string serviceName = System.Configuration.ConfigurationSettings.AppSettings["ServiceName"];
    string machineName = System.Configuration.ConfigurationSettings.AppSettings["MachineName"];

    try
    {
        var service = new ServiceController(serviceName, machineName);
        if (service.Status != ServiceControllerStatus.Stopped)
        {
            service.Stop();
            service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
        }

        service.Start();
        service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);

    }
    catch (Exception)
    {
    }
}

Hope 1 this Helps.

Score: 2

galets code snippet above is a great start. However, keep 10 in mind it assumes that the service has 9 already started, or, more importantly, that 8

sc.Status == System.ServiceProcess.ServiceControllerStatus.Running

Also, it may important to, at some point 7 during code execution, call

sc.Refresh();

because the properties 6 values (such as ServiceControllerStatus) may 5 not reflect the actual properties of the 4 service. For instance, you may call

sc.Start();

and 3 wait indefinitely when this command executes

sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running)

Here 2 is a version of this code that I coded with 1 those considerations in mind.

            //Restart Content Service on DEV. 
        String svcName = "TheServiceName";
        String machineName = "TheMachineName";
        var sc = new System.ServiceProcess.ServiceController(svcName, machineName);
        Console.WriteLine("Stopping Service '{0}' on machine '{1}", svcName, machineName);
        sc.Stop();
        sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);          

        //sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
        do
        {
            try
            {
                sc.Refresh();
                if (sc.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    Console.WriteLine("Code has detected that servive start is pending, waiting 5 seconds to see if status changes..");
                    System.Threading.Thread.Sleep(5000);
                }
                else
                {
                    Console.WriteLine("waiting 5 seconds and retrying start..");
                    System.Threading.Thread.Sleep(5000);
                    Console.WriteLine("Attempt Starting Service '{0}' on machine '{1}", svcName, machineName);
                    sc.Start();
                }
            }

            catch(Exception ex)
            {
                //If it is already running, then abort do while
                if (ex.InnerException.Message == "An instance of the service is already running")
                {
                    Console.WriteLine(ex.InnerException.Message);
                    continue;
                }
                Console.WriteLine(ex.InnerException.ToString());
            }
        } while (sc.Status != System.ServiceProcess.ServiceControllerStatus.Running);
Score: 1

Here is a ServiceExtension that can Start 12 and Stop Services on remote pc's.

And it 11 can set the Startup type of the service, even 10 to "automatic (delayed)"

modified 9 version from this Answer to work on remote machines.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.ServiceProcess;

namespace Helpers
{
    public enum ServiceStartModeEx
    {
        Automatic = 2,
        Manual = 3,
        Disabled = 4,
        DelayedAutomatic = 99
    }
    /// <summary>
    /// Extensions to the ServiceController class.
    /// </summary>
    public static class ServiceControlerExtensions
    {
        /// <summary>
        /// Set the start mode for the service.
        /// </summary>
        /// <param name="serviceController">The service controller.</param>
        /// <param name="mode">The desired start mode.</param>
        public static void SetStartMode(this ServiceController serviceController, ServiceStartModeEx mode)
        {
            IntPtr serviceManagerHandle = OpenServiceManagerHandle(serviceController);
            IntPtr serviceHandle = OpenServiceHandle(serviceController, serviceManagerHandle);

            try
            {
                if (mode == ServiceStartModeEx.DelayedAutomatic)
                {
                    ChangeServiceStartType(serviceHandle, ServiceStartModeEx.Automatic);
                    ChangeDelayedAutoStart(serviceHandle, true);
                }
                else
                {
                    // Delayed auto-start overrides other settings, so it must be set first.
                    ChangeDelayedAutoStart(serviceHandle, false);
                    ChangeServiceStartType(serviceHandle, mode);
                }
            }
            finally
            {
                if (serviceHandle != IntPtr.Zero)
                {
                    CloseServiceHandle(serviceHandle);
                }
                if (serviceManagerHandle != IntPtr.Zero)
                {
                    CloseServiceHandle(serviceManagerHandle);
                }
            }
        }

        private static IntPtr OpenServiceHandle(ServiceController serviceController, IntPtr serviceManagerHandle)
        {
            var serviceHandle = OpenService(
                                            serviceManagerHandle,
                                            serviceController.ServiceName,
                                            SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);

            if (serviceHandle == IntPtr.Zero)
            {
                throw new ExternalException("Open Service Error");
            }
            return serviceHandle;
        }

        private static IntPtr OpenServiceManagerHandle(ServiceController serviceController)
        {
            var machineName = string.IsNullOrWhiteSpace(serviceController.MachineName)
                ? null
                : serviceController.MachineName;
            IntPtr serviceManagerHandle = OpenSCManager(machineName, null, SC_MANAGER_ALL_ACCESS);
            if (serviceManagerHandle == IntPtr.Zero)
            {
                throw new ExternalException("Open Service Manager Error");
            }
            return serviceManagerHandle;
        }

        private static void ChangeServiceStartType(IntPtr serviceHandle, ServiceStartModeEx mode)
        {
            bool result = ChangeServiceConfig(
                                             serviceHandle,
                                             SERVICE_NO_CHANGE,
                                             (uint)mode,
                                             SERVICE_NO_CHANGE,
                                             null,
                                             null,
                                             IntPtr.Zero,
                                             null,
                                             null,
                                             null,
                                             null);

            if (result == false)
            {
                ThrowLastWin32Error("Could not change service start type");
            }
        }

        private static void ChangeDelayedAutoStart(IntPtr hService, bool delayed)
        {
            // Create structure that contains DelayedAutoStart property.
            SERVICE_DELAYED_AUTO_START_INFO info = new SERVICE_DELAYED_AUTO_START_INFO();

            // Set the DelayedAutostart property in that structure.
            info.fDelayedAutostart = delayed;

            // Allocate necessary memory.
            IntPtr hInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SERVICE_DELAYED_AUTO_START_INFO)));

            // Convert structure to pointer.
            Marshal.StructureToPtr(info, hInfo, true);

            // Change the configuration.
            bool result = ChangeServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, hInfo);

            // Release memory.
            Marshal.FreeHGlobal(hInfo);

            if (result == false)
            {
                ThrowLastWin32Error("Could not set service to delayed automatic");
            }
        }

        private static void ThrowLastWin32Error(string messagePrefix)
        {
            int nError = Marshal.GetLastWin32Error();
            var win32Exception = new Win32Exception(nError);
            string message = string.Format("{0}: {1}", messagePrefix, win32Exception.Message);
            throw new ExternalException(message);
        }

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr OpenService(
            IntPtr hSCManager,
            string lpServiceName,
            uint dwDesiredAccess);

        [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode,
            SetLastError = true)]
        private static extern IntPtr OpenSCManager(
            string machineName,
            string databaseName,
            uint dwAccess);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern Boolean ChangeServiceConfig(
            IntPtr hService,
            UInt32 nServiceType,
            UInt32 nStartType,
            UInt32 nErrorControl,
            String lpBinaryPathName,
            String lpLoadOrderGroup,
            IntPtr lpdwTagId,
            [In] char[] lpDependencies,
            String lpServiceStartName,
            String lpPassword,
            String lpDisplayName);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ChangeServiceConfig2(
            IntPtr hService,
            int dwInfoLevel,
            IntPtr lpInfo);

        [DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")]
        private static extern int CloseServiceHandle(IntPtr hSCObject);

        private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
        private const uint SERVICE_QUERY_CONFIG = 0x00000001;
        private const uint SERVICE_CHANGE_CONFIG = 0x00000002;
        private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;

        private const int SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct SERVICE_DELAYED_AUTO_START_INFO
        {
            public bool fDelayedAutostart;
        }
    }
}

You 8 can start a service like this

 using System.ServiceProcess;

serviceName 7 = "the name of the service"

machineName 6 = "the name of the remote/local host"

 var service = new ServiceController(serviceName, machineName);
 try
 {
     service.SetStartMode(ServiceStartModeEx.DelayedAutomatic);
     service.Start();
 }

 finally
 {
     service.Close();
 }

You 5 can stop a service like this

var service = new ServiceController(serviceName, machineName);
try
{
    if (service.CanStop)
    {
        service.SetStartMode(ServiceStartModeEx.Disabled);
        service.Stop();

    }
}

finally
{
    service.Close();
}

To grant a user 4 rights to start and stop a service on a 3 remote pc you have to set some service rights, you 2 can google what subinacl.exe is and where 1 to download it.

C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl.exe /service SERVICENAME /grant=MACHINENAME\USERNAME=F

More Related questions