以编程方式启用Windows服务

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)

Mik*_*ray 8

我不认为编辑注册表是推荐的方法.不幸的是,它没有暴露在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)


Dav*_*lli 5

有几种方法可以更改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)