Как программно остановить / запустить службу windows на удаленном устройстве?
Я хочу написать консоль или нажать один раз приложение WinForms, которое программно остановит и / или запустит службу windows на удаленном устройстве.
Обе коробки работают под управлением .NET 3.5-какие .NET API доступны для этого?
9 ответов:
В 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);
Вы также можете сделать это из командной консоли, используя команду
sc:sc <server> start [service name] sc <server> stop [service name]Использовать
sc <server> query | find "SERVICE_NAME"Чтобы получить список имен служб.
Вариант
<server>имеет вид\\ServerNameПример
sc \\MyServer stop scheduleостановит службу планировщика.
Вам необходимо иметь разрешение на администрирование служб в удаленном окне.
Как говорит Mehrdad, вы также можете использовать WMI. Оба метода работают для start и stop, но WMI требует больше кода и даст вам больше доступа к другим ресурсам
Если вы не хотите кодировать его самостоятельно, PsService от Microsoft/Sysinternals-это инструмент командной строки, который делает то, что вы хотите.
Вы можете использовать
System.ManagementAPI (WMI) для удаленного управления службами. WMI-это универсальный API для выполнения административных задач.Для этой задачи, однако, я предлагаю вам использовать более простой в использовании класс
System.ServiceProcess.ServiceController.
Если вам нужно получить название сервиса:
Выполните это из командной строки:
Sc query
Вы увидите, например, что имя службы SQL Server - "MSSQL$SQLEXPRESS".
Итак, чтобы остановить службу SQL Server в C#:
ServiceController controller = new ServiceController(); controller.MachineName = "Machine1"; controller.ServiceName = "MSSQL$SQLEXPRESS"; if(controller.Status == ServiceControllerStatus.Running) controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped);
Приведенный выше фрагмент кода Galets-отличное начало. Однако имейте в виду, что он предполагает, что служба уже началась, или, что более важно, что
sc.Status == System.ServiceProcess.ServiceControllerStatus.RunningКроме того, может быть важно в какой-то момент во время выполнения кода вызвать
sc.Refresh();Потому что значения свойств (такие как ServiceControllerStatus) могут не отражать фактические свойства сервиса. Например, вы можете вызвать
sc.Start();И ждать бесконечно, когда эта команда будет выполнена
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running)Здесь есть версия этого кода, которую я закодировал с учетом этих соображений.
//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);
Я сделал, как показано ниже:
Примечание:
- Если вы не запустили свою службу, если вы пытаетесь остановить ее, она выдаст исключение.
- Если вы настроите эти вещи в своей сети.config, исключение, связанное с конфигурацией, не придет. Не нужно ничего делать в IIS.
В
Web.Configпод<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>В Моем Классе Обслуживания:
private void RestartService() { string serviceName = System.Configuration.ConfigurationSettings.AppSettings["ServiceName"]; string machineName = System.Configuration.ConfigurationSettings.AppSettings["MachineName"]; try { var service = new ServiceController(serviceName); if (service.Status != ServiceControllerStatus.Stopped) { service.Stop(); service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped); } service.Start(); service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running); } catch (Exception) { } }Надеюсь, это поможет.,
Вот ServiceExtension, который может запускать и останавливать службы на удаленных компьютерах.
И он может установить тип запуска службы, даже "автоматический (с задержкой)"
Модифицированная версия из этогоответа для работы на удаленных машинах.
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; } } }Вы можете запустить такую службу
using System.ServiceProcess;ServiceName = "имя службы"
MachineName = "имя удаленного / локального хоста"
var service = new ServiceController(serviceName, machineName); try { service.SetStartMode(ServiceStartModeEx.DelayedAutomatic); service.Start(); } finally { service.Close(); }Вы можете остановить такую услугу, как это
var service = new ServiceController(serviceName, machineName); try { if (service.CanStop) { service.SetStartMode(ServiceStartModeEx.Disabled); service.Stop(); } } finally { service.Close(); }Чтобы предоставить пользователю права на запуск и остановку службы на удаленном компьютере, вы должны установить некоторые права службы, вы можете google, что subinacl.exe есть и где его скачать.
C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl.exe /service SERVICENAME /grant=MACHINENAME\USERNAME=F
Comments