Como posso programaticamente parar / iniciar um serviço do Windows em uma checkbox remota?

Eu quero escrever um console ou o aplicativo Click Once WinForms que irá parar programaticamente e / ou iniciar um serviço do Windows em uma checkbox remota.

Ambas as checkboxs estão executando o .NET 3.5 – quais APIs .NET estão disponíveis para realizar isso?

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

Você também pode fazer isso em um console de comando usando o comando sc :

  sc  start [service name] sc  stop [service name] 

Usar

 sc  query | find "SERVICE_NAME" 

para obter uma lista de nomes de serviços.

A opção tem o formulário \\ServerName

Exemplo

sc \\MyServer stop schedule irá parar o serviço do Agendador.

ServiceController .

Você precisa ter permissão para administrar os serviços na checkbox remota.

Como Mehrdad diz, você também pode usar o WMI. Ambos os methods funcionam para iniciar e parar, mas o WMI requer mais codificação e fornecerá mais access a outros resources

Se você não quiser codificar você mesmo, o PsService da Microsoft / Sysinternals é uma ferramenta de linha de comando que faz o que você deseja.

Você pode usar o System.Management APIs (WMI) para controlar os serviços remotamente. O WMI é a API genérica para executar tarefas administrativas.

Para esse problema, no entanto, sugiro que você use o mais fácil de usar class System.ServiceProcess.ServiceController .

se você precisar obter o nome do serviço:

execute isto a partir da linha de comando:

consulta sc

Você verá, por exemplo, que o nome do serviço do SQL Server é ‘MSSQL $ SQLEXPRESS’.

Então, para parar o serviço do SQL Server em C #:

  ServiceController controller = new ServiceController(); controller.MachineName = "Machine1"; controller.ServiceName = "MSSQL$SQLEXPRESS"; if(controller.Status == ServiceControllerStatus.Running) controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped); 

O trecho de código de galets acima é um ótimo começo. No entanto, lembre-se de que o serviço já foi iniciado ou, mais importante, que

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

Além disso, pode ser importante, em algum momento durante a execução do código, chamar

 sc.Refresh(); 

porque os valores das propriedades (como ServiceControllerStatus) podem não refletir as propriedades reais do serviço. Por exemplo, você pode ligar

 sc.Start(); 

e esperar indefinidamente quando este comando executa

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

Aqui está uma versão deste código que codifiquei com essas considerações em mente.

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

Eu fiz como abaixo:

Nota:

  1. Se você não iniciou o seu serviço se você está tentando pará-lo, será lançada uma exceção.
  2. Se você configurar essas coisas em seu web.config, a exceção relacionada à configuração não será exibida. Não há necessidade de fazer nada no IIS.

No Web.Config em

          

Na minha class de serviço:

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

Espero que isto ajude.,

Aqui está um ServiceExtension que pode iniciar e parar serviços em PCs remotos.

E pode definir o tipo de boot do serviço, mesmo para “automático (atrasado)”

versão modificada desta resposta para trabalhar em máquinas remotas.

 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 } ///  /// Extensions to the ServiceController class. ///  public static class ServiceControlerExtensions { ///  /// Set the start mode for the service. ///  /// The service controller. /// The desired start mode. 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; } } } 

Você pode iniciar um serviço como este

  using System.ServiceProcess; 

serviceName = “o nome do serviço”

machineName = “o nome do host remoto / local”

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

Você pode parar um serviço como este

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

Para conceder um direito de usuário para iniciar e parar um serviço em um PC remoto, você deve definir alguns direitos de serviço, você pode pesquisar no Google o que é subinacl.exe e onde baixá-lo.

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