From 40b566d3309f529706d270ded41746c77bc4e60d Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Thu, 23 Jul 2020 00:00:00 +0800 Subject: [PATCH] Add `refresh` command --- src/WinSW.Core/Native/Service.cs | 22 +++++++++++++ src/WinSW.Core/Native/ServiceApis.cs | 16 +++++++++- src/WinSW/Program.cs | 46 ++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/WinSW.Core/Native/Service.cs b/src/WinSW.Core/Native/Service.cs index 3700cf8..41ccf4b 100644 --- a/src/WinSW.Core/Native/Service.cs +++ b/src/WinSW.Core/Native/Service.cs @@ -189,6 +189,28 @@ namespace WinSW.Native } } + /// + 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."); + } + } + /// internal void Delete() { diff --git a/src/WinSW.Core/Native/ServiceApis.cs b/src/WinSW.Core/Native/ServiceApis.cs index be95d0e..e11adc9 100644 --- a/src/WinSW.Core/Native/ServiceApis.cs +++ b/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, diff --git a/src/WinSW/Program.cs b/src/WinSW/Program.cs index ead3ba0..22e05b5 100644 --- a/src/WinSW/Program.cs +++ b/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() {