Pārlūkot izejas kodu

Add `refresh` command

NextTurn 5 gadi atpakaļ
vecāks
revīzija
40b566d330

+ 22 - 0
src/WinSW.Core/Native/Service.cs

@@ -189,6 +189,28 @@ namespace WinSW.Native
             }
         }
 
+        /// <exception cref="CommandException" />
+        internal void ChangeConfig(
+            string displayName,
+            ServiceStartMode startMode)
+        {
+            if (!ChangeServiceConfig(
+                this.handle,
+                default,
+                startMode,
+                default,
+                null,
+                null,
+                IntPtr.Zero,
+                null,
+                null,
+                null,
+                displayName))
+            {
+                Throw.Command.Win32Exception("Failed to change service config.");
+            }
+        }
+
         /// <exception cref="CommandException" />
         internal void Delete()
         {

+ 15 - 1
src/WinSW.Core/Native/ServiceApis.cs

@@ -8,6 +8,20 @@ namespace WinSW.Native
 {
     internal static class ServiceApis
     {
+        [DllImport(Libraries.Advapi32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfigW")]
+        internal static extern bool ChangeServiceConfig(
+            IntPtr serviceHandle,
+            ServiceType serviceType,
+            ServiceStartMode startType,
+            ServiceErrorControl errorControl,
+            string? binaryPath,
+            string? loadOrderGroup,
+            IntPtr tagId,
+            StringBuilder? dependencies, // TODO
+            string? serviceStartName,
+            string? password,
+            string displayName);
+
         [DllImport(Libraries.Advapi32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ChangeServiceConfig2W")]
         internal static extern bool ChangeServiceConfig2(IntPtr serviceHandle, ServiceConfigInfoLevels infoLevel, in SERVICE_DESCRIPTION info);
 
@@ -30,7 +44,7 @@ namespace WinSW.Native
             ServiceStartMode startType,
             ServiceErrorControl errorControl,
             string binaryPath,
-            string? loaderOrderGroup,
+            string? loadOrderGroup,
             IntPtr tagId,
             StringBuilder? dependencies, // TODO
             string? serviceStartName,

+ 46 - 0
src/WinSW/Program.cs

@@ -159,6 +159,10 @@ namespace WinSW
                     TestWait();
                     return;
 
+                case "refresh":
+                    Refresh();
+                    return;
+
                 case "help":
                 case "--help":
                 case "-h":
@@ -642,6 +646,48 @@ namespace WinSW
                 wsvc.RaiseOnStop();
             }
 
+            void Refresh()
+            {
+                if (!elevated)
+                {
+                    Elevate();
+                    return;
+                }
+
+                using ServiceManager scm = ServiceManager.Open();
+                try
+                {
+                    using Service sc = scm.OpenService(descriptor.Id);
+
+                    sc.ChangeConfig(descriptor.Caption, descriptor.StartMode);
+
+                    sc.SetDescription(descriptor.Description);
+
+                    SC_ACTION[] actions = descriptor.FailureActions;
+                    if (actions.Length > 0)
+                    {
+                        sc.SetFailureActions(descriptor.ResetFailureAfter, actions);
+                    }
+
+                    bool isDelayedAutoStart = descriptor.StartMode == ServiceStartMode.Automatic && descriptor.DelayedAutoStart;
+                    if (isDelayedAutoStart)
+                    {
+                        sc.SetDelayedAutoStart(true);
+                    }
+
+                    string? securityDescriptor = descriptor.SecurityDescriptor;
+                    if (securityDescriptor != null)
+                    {
+                        // throws ArgumentException
+                        sc.SetSecurityDescriptor(new RawSecurityDescriptor(securityDescriptor));
+                    }
+                }
+                catch (CommandException e) when (e.InnerException is Win32Exception inner && inner.NativeErrorCode == Errors.ERROR_SERVICE_DOES_NOT_EXIST)
+                {
+                    ThrowNoSuchService(inner);
+                }
+            }
+
             // [DoesNotReturn]
             void Elevate()
             {