Add `refresh` command

pull/589/head
NextTurn 2020-07-23 00:00:00 +08:00 committed by Next Turn
parent 80323eaab8
commit 40b566d330
3 changed files with 83 additions and 1 deletions

View File

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

View File

@ -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,

View File

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