How can I programmatically stop/start a windows service on a remote box?

后端 未结 9 1705
清歌不尽
清歌不尽 2020-11-27 05:17

I want to write a console or Click Once WinForms app that will programmatically stop and/or start a windows service on a remote box.

Both boxes are running .NET 3.5

相关标签:
9条回答
  • 2020-11-27 05:28

    ServiceController.

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

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

    0 讨论(0)
  • 2020-11-27 05:30

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

    0 讨论(0)
  • 2020-11-27 05:30

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

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

    modified 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 can start a service like this

     using System.ServiceProcess;
    

    serviceName = "the name of the service"

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

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

    You 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 rights to start and stop a service on a remote pc you have to set some service rights, you can google what subinacl.exe is and where to download it.

    C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl.exe /service SERVICENAME /grant=MACHINENAME\USERNAME=F
    
    0 讨论(0)
  • 2020-11-27 05:32

    You can also do this from a command console 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 service names.

    The option <server> has the form \\ServerName

    Example

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

    0 讨论(0)
  • 2020-11-27 05:37

    if you need to get the name of the Service:

    run this from the command line:

    sc query

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

    So to stop the 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);
    
    0 讨论(0)
  • 2020-11-27 05:38

    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 this Helps.

    0 讨论(0)
提交回复
热议问题