Fix the stop logic

pull/603/head
NextTurn 2020-02-28 00:00:00 +08:00 committed by Next Turn
parent 9d7adbf70e
commit 08c836ccc5
3 changed files with 36 additions and 16 deletions

View File

@ -117,9 +117,9 @@ namespace WinSW.Native
} }
/// <exception cref="CommandException" /> /// <exception cref="CommandException" />
internal Service OpenService(string serviceName) internal Service OpenService(string serviceName, ServiceAccess access = ServiceAccess.ALL_ACCESS)
{ {
IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, ServiceAccess.ALL_ACCESS); IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, access);
if (serviceHandle == IntPtr.Zero) if (serviceHandle == IntPtr.Zero)
{ {
Throw.Command.Win32Exception("Failed to open the service."); Throw.Command.Win32Exception("Failed to open the service.");
@ -171,6 +171,24 @@ namespace WinSW.Native
} }
} }
/// <exception cref="CommandException" />
internal void SetStatus(IntPtr statusHandle, ServiceControllerStatus state)
{
if (!QueryServiceStatus(this.handle, out SERVICE_STATUS status))
{
Throw.Command.Win32Exception("Failed to query service status.");
}
status.CheckPoint = 0;
status.WaitHint = 0;
status.CurrentState = state;
if (!SetServiceStatus(statusHandle, status))
{
Throw.Command.Win32Exception("Failed to set service status.");
}
}
/// <exception cref="CommandException" /> /// <exception cref="CommandException" />
internal void Delete() internal void Delete()
{ {

View File

@ -51,7 +51,7 @@ namespace WinSW.Native
[DllImport(Libraries.Advapi32, SetLastError = true)] [DllImport(Libraries.Advapi32, SetLastError = true)]
internal static extern bool SetServiceObjectSecurity(IntPtr serviceHandle, SecurityInfos securityInformation, byte[] securityDescriptor); internal static extern bool SetServiceObjectSecurity(IntPtr serviceHandle, SecurityInfos securityInformation, byte[] securityDescriptor);
[DllImport(Libraries.Advapi32)] [DllImport(Libraries.Advapi32, SetLastError = true)]
internal static extern bool SetServiceStatus(IntPtr serviceStatusHandle, in SERVICE_STATUS serviceStatus); internal static extern bool SetServiceStatus(IntPtr serviceStatusHandle, in SERVICE_STATUS serviceStatus);
// SERVICE_ // SERVICE_
@ -152,7 +152,7 @@ namespace WinSW.Native
internal struct SERVICE_STATUS internal struct SERVICE_STATUS
{ {
public int ServiceType; public ServiceType ServiceType;
public ServiceControllerStatus CurrentState; public ServiceControllerStatus CurrentState;
public int ControlsAccepted; public int ControlsAccepted;
public int Win32ExitCode; public int Win32ExitCode;

View File

@ -17,8 +17,6 @@ namespace WinSW
{ {
public class WrapperService : ServiceBase, IEventLogger public class WrapperService : ServiceBase, IEventLogger
{ {
private ServiceApis.SERVICE_STATUS wrapperServiceStatus;
private readonly Process process = new Process(); private readonly Process process = new Process();
private readonly ServiceDescriptor descriptor; private readonly ServiceDescriptor descriptor;
private Dictionary<string, string>? envs; private Dictionary<string, string>? envs;
@ -415,13 +413,12 @@ namespace WinSW
this.RequestAdditionalTime(serviceWaitHint); this.RequestAdditionalTime(serviceWaitHint);
} }
private void SignalShutdownComplete() private void SignalStopped()
{ {
IntPtr handle = this.ServiceHandle; using ServiceManager scm = ServiceManager.Open();
this.wrapperServiceStatus.CheckPoint++; using Service sc = scm.OpenService(this.ServiceName, ServiceApis.ServiceAccess.QUERY_STATUS);
// WriteEvent("SignalShutdownComplete " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint);
this.wrapperServiceStatus.CurrentState = ServiceControllerStatus.Stopped; sc.SetStatus(this.ServiceHandle, ServiceControllerStatus.Stopped);
ServiceApis.SetServiceStatus(handle, this.wrapperServiceStatus);
} }
private void StartProcess(Process processToStart, string arguments, string executable, LogHandler? logHandler, bool redirectStdin) private void StartProcess(Process processToStart, string arguments, string executable, LogHandler? logHandler, bool redirectStdin)
@ -442,12 +439,17 @@ namespace WinSW
// if we finished orderly, report that to SCM. // if we finished orderly, report that to SCM.
// by not reporting unclean shutdown, we let Windows SCM to decide if it wants to // by not reporting unclean shutdown, we let Windows SCM to decide if it wants to
// restart the service automatically // restart the service automatically
if (process.ExitCode == 0) try
{ {
this.SignalShutdownComplete(); if (process.ExitCode == 0)
{
this.SignalStopped();
}
}
finally
{
Environment.Exit(process.ExitCode);
} }
Environment.Exit(process.ExitCode);
} }
} }