Ala*_*n B 3 c# windows-services
我试图通过修改注册表中的值以编程方式启用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);
}
}
Run Code Online (Sandbox Code Playgroud)
我不认为编辑注册表是推荐的方法.不幸的是,它没有暴露在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" });
}
}
Run Code Online (Sandbox Code Playgroud)
有几种方法可以更改Windows服务的启动类型(请参阅此问题).如果我没记错,WMI方法在测试时工作但不完全可靠,所以我使用了Windows API函数ChangeServiceConfig.我从未尝试过注册表方法.我认为这将是三个选项中最不稳定的.
请注意,如果您想要"自动(延迟启动)"模式,则需要调用ChangeServiceConfig2.
public void ChangeServiceStartType(string serviceName, ServiceStartupType 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($"Failed to obtain a handle to service '{serviceName}'.");
}
//Change the start mode
bool changeServiceSuccess = ChangeServiceConfig(serviceHandle, SERVICE_NO_CHANGE, (uint)startType, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, null, null, null);
if (!changeServiceSuccess)
{
string msg = $"Failed to update service configuration for service '{serviceName}'. ChangeServiceConfig returned error {Marshal.GetLastWin32Error()}.";
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 bool ChangeServiceConfig(
IntPtr hService,
uint nServiceType,
uint nStartType,
uint 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;
public enum ServiceStartupType : uint
{
/// <summary>
/// A device driver started by the system loader. This value is valid only for driver services.
/// </summary>
BootStart = 0,
/// <summary>
/// A device driver started by the IoInitSystem function. This value is valid only for driver services.
/// </summary>
SystemStart = 1,
/// <summary>
/// A service started automatically by the service control manager during system startup.
/// </summary>
Automatic = 2,
/// <summary>
/// A service started by the service control manager when a process calls the StartService function.
/// </summary>
Manual = 3,
/// <summary>
/// A service that cannot be started. Attempts to start the service result in the error code ERROR_SERVICE_DISABLED.
/// </summary>
Disabled = 4
}
Run Code Online (Sandbox Code Playgroud)