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()
{