以编程方式启用Windows服务

我试图通过修改注册表中的值以编程方式启用Windows服务,如下所示。 价值确实在变化。 但是,之后我无法启动该服务,因为Windows仍然将其视为已禁用。

public void EnabledTheService(string serviceName) { try { RegistryKey key = Registry.LocalMachine .OpenSubKey(@"SYSTEM\CurrentControlSet\Services\" + serviceName, true); key.SetValue("Start", 2); } catch (Exception ex) { Console.Write(ex.Message); } } public void StartService(string serviceName) { ServiceController service = new ServiceController(serviceName); try { service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 0, 20)); } catch (Exception ex) { Console.Write(ex.Message); } } 

有几种方法可以更改Windows服务的启动类型(请参阅此问题 )。 如果我没记错,WMI方法在我测试时起作用但不完全可靠,所以我使用了Windows API函数ChangeServiceConfig 。 我从未尝试过注册表方法。 我认为这将是三个选项中最不稳定的。 我有C#代码调用ChangeServiceConfig,但不是在我面前。 我明天会尝试添加它。 pinovke文档是一个很好的起点。

更新:以下是使用Windows API的方法:

 private void ChangeServiceStartType(string serviceName, StartupTypeOptions startType) { //Obtain a handle to the service control manager database IntPtr scmHandle = OpenSCManager(null, null, SC_MANAGER_CONNECT); if (scmHandle == IntPtr.Zero) { throw new Exception("Failed to obtain a handle to the service control manager database."); } //Obtain a handle to the specified windows service IntPtr serviceHandle = OpenService(scmHandle, serviceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG); if (serviceHandle == IntPtr.Zero) { throw new Exception(string.Format("Failed to obtain a handle to service \"{0}\".", serviceName)); } bool changeServiceSuccess = ChangeServiceConfig(serviceHandle, SERVICE_NO_CHANGE, (uint)startType, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, null, null, null); if (!changeServiceSuccess) { string msg = string.Format("Failed to update service configuration for service \"{0}\". ChangeServiceConfig returned error {1}.", serviceName, Marshal.GetLastWin32Error().ToString()); throw new Exception(msg); } //Clean up if (scmHandle != IntPtr.Zero) CloseServiceHandle(scmHandle); if (serviceHandle != IntPtr.Zero) CloseServiceHandle(serviceHandle); } [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport("advapi32.dll", CharSet = CharSet.Auto, 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", EntryPoint = "CloseServiceHandle")] private static extern int CloseServiceHandle(IntPtr hSCObject); private const uint SC_MANAGER_CONNECT = 0x0001; private const uint SERVICE_QUERY_CONFIG = 0x00000001; private const uint SERVICE_CHANGE_CONFIG = 0x00000002; private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF; private enum StartupTypeOptions : uint { BootStart = 0, //A device driver started by the system loader. This value is valid only for driver services. SystemStart = 1, //A device driver started by the IoInitSystem function. This value is valid only for driver services. Automatic = 2, //A service started automatically by the service control manager during system startup. Manual = 3, //A service started by the service control manager when a process calls the StartService function. Disabled = 4 //A service that cannot be started. Attempts to start the service result in the error code ERROR_SERVICE_DISABLED. } 

我不认为编辑注册表是建议的方法。 不幸的是,它没有在ServiceController类中公开。 我建议使用WMI,它具有ChangeStartMode方法(您需要添加对System.Management.dll的引用):

 using System.Management; public static void EnableTheService(string serviceName) { using (var mo = new ManagementObject(string.Format("Win32_Service.Name=\"{0}\"", serviceName))) { mo.InvokeMethod("ChangeStartMode", new object[] { "Automatic" }); } }