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" />
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)
{
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" />
internal void Delete()
{

View File

@ -51,7 +51,7 @@ namespace WinSW.Native
[DllImport(Libraries.Advapi32, SetLastError = true)]
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);
// SERVICE_
@ -152,7 +152,7 @@ namespace WinSW.Native
internal struct SERVICE_STATUS
{
public int ServiceType;
public ServiceType ServiceType;
public ServiceControllerStatus CurrentState;
public int ControlsAccepted;
public int Win32ExitCode;

View File

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