如何以编程方式停止/启动远程盒子上的Windows服务?
我想编写一个控制台或单击一次WinForms应用程序将以编程方式停止和/或启动远程盒子上的Windows服务。
这两个框都运行.NET 3.5 – 什么.NET API可用来完成这个?
在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
的forms
例
sc \\MyServer stop schedule
将停止计划程序服务。
ServiceController 。
您需要具有pipe理远程盒上的服务的权限。
正如Mehrdad所说,你也可以使用WMI。 这两种方法都适用于启动和停止,但是WMI需要更多的编码,并且可以让您更多地访问其他资源
如果你不想自己编写代码,Microsoft / Sysinternals的PsService是一个命令行工具,它可以做你想做的事情。
您可以使用System.Management
API(WMI)远程控制服务。 WMI是执行pipe理任务的通用API。
不过,对于这个问题,我build议你使用更容易使用的System.ServiceProcess.ServiceController
类。
上面的代码片段是一个很好的开始。 但是,请记住,假设服务已经开始,或者更重要的是,
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);
如果您需要获取服务的名称:
从命令行运行这个:
sc查询
你会看到,例如,SQL Server的服务名称是“MSSQL $ SQLEXPRESS”。
所以要停止在C#中的SQL Server服务:
ServiceController controller = new ServiceController(); controller.MachineName = "Machine1"; controller.ServiceName = "MSSQL$SQLEXPRESS"; if(controller.Status == ServiceControllerStatus.Running) controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped);
我做了如下:
注意:
- 如果你试图阻止它,如果你没有开始你的服务会抛出exception。
- 如果你在web.config中configuration这些东西,configuration相关的exception将不会出现。 无需在IIS中做任何事情。
在<configuration>
下的Web.Config
<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,可以启动和停止远程PC上的服务。
它可以设置服务的启动types,甚至“自动(延迟)”
从这个答案修改的版本在远程机器上工作。
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(); }
要授予用户在远程PC上启动和停止服务的权限,您必须设置一些服务权限,您可以谷歌什么subinacl.exe是在哪里下载它。
C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl.exe /service SERVICENAME /grant=MACHINENAME\USERNAME=F