Définir le service existant sur «Auto (démarrage différé)»

J’essaie de définir un service Windows déjà installé pour un démarrage automatique retardé en C #. Comment définir un service Windows sur

Automatic (Delayed Start) 

Impossible de trouver cette valeur dans l’énumération ServiceStartMode.

Modifier: 1

 public class ServiceAutoStartInfo { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct SERVICE_DELAYED_AUTO_START_INFO { public bool fDelayedAutostart; } [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, IntPtr lpInfo); // Service configuration parameter const int SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3; public bool ChangeDelayedAutoStart(IntPtr hService, bool delayed) { // Validate service handle if (hService != IntPtr.Zero) { // Create SERVICE_DELAYED_AUTO_START_INFO info = new SERVICE_DELAYED_AUTO_START_INFO(); // Set the DelayedAutostart property 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); return result; } return false; } } 

Voici comment je l’appelle:

 var controller = new ServiceController(s.ServiceName); var autoDelay = new ServiceAutoStartInfo(); autoDelay.ChangeDelayedAutoStart(controller.ServiceHandle.DangerousGetHandle(), true); 

Mais sans résultat.

Recherchez l’appel de la fonction Windows ChangeServiceConfig2 , avec dwInfoLevel de la dwInfoLevel SERVICE_CONFIG_DELAYED_AUTO_START_INFO et une structure SERVICE_DELAYED_AUTO_START_INFO avec fDelayedAutostart défini sur TRUE .

Ou, vous pouvez le faire avec la ligne de commande:

 sc.exe config  start= delayed-auto 

J’utilise ce qui suit, qui fonctionne pour moi sur Windows 7 (lorsqu’il est exécuté en tant qu’administrateur):

 using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.ServiceProcess; namespace ServiceManager { ///  /// 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(); 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 (serviceHandle != 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() { IntPtr serviceManagerHandle = OpenSCManager(null, 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(ssortingng messagePrefix) { int nError = Marshal.GetLastWin32Error(); var win32Exception = new Win32Exception(nError); ssortingng message = ssortingng.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, ssortingng lpServiceName, uint dwDesiredAccess); [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr OpenSCManager( ssortingng machineName, ssortingng databaseName, uint dwAccess); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern Boolean ChangeServiceConfig( IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, Ssortingng lpBinaryPathName, Ssortingng lpLoadOrderGroup, IntPtr lpdwTagId, [In] char[] lpDependencies, Ssortingng lpServiceStartName, Ssortingng lpPassword, Ssortingng 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; } } } namespace ServiceManager { public enum ServiceStartModeEx { Automatic = 2, Manual = 3, Disabled = 4, DelayedAutomatic = 99 } } 

Vous l’appelez comme ça:

 var serviceController = new ServiceController("Windows Update"); try { serviceController.SetStartMode(ServiceStartModeEx.DelayedAutomatic); } finally { serviceController.Close(); } 

Mise à jour: Ceci ne fonctionne que pour configurer de nouveaux services et n’est pas ce que l’OP a demandé:

Vous pouvez utiliser la propriété DelayedAutoStart de ServiceInstaller .

 installer.DelayedAutoStart = true; 

Je crois que vous devez combiner les deux méthodes ChangeServiceConfig et ChangeServiceConfig2.

Le pseudo-code suit:

 public static void ChangeServiceStartupType(ServiceStartupType type, ...) { if (type == AutomaticDelayed) { if (ChangeServiceConfig2(.., DelayedAutoStart, ..)) { ChangeServiceConfig(.., Automatic, ..); } } else { ChangeServiceConfig2(.., !DelayedAutoStart, ..) ChangeServiceConfig(.., type, ..) } } 

edit: vous devez également supprimer “delay-automatic” lorsque vous demandez un type de démarrage non différé Sinon, il ne sera pas possible de définir le type “automatique”. (“automatique-différé” remplace “automatique”)