diff --git a/src/WinSW.Core/Native/Service.cs b/src/WinSW.Core/Native/Service.cs
index 85f4e19..3700cf8 100644
--- a/src/WinSW.Core/Native/Service.cs
+++ b/src/WinSW.Core/Native/Service.cs
@@ -117,9 +117,9 @@ namespace WinSW.Native
}
///
- 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
}
}
+ ///
+ 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.");
+ }
+ }
+
///
internal void Delete()
{
diff --git a/src/WinSW.Core/Native/ServiceApis.cs b/src/WinSW.Core/Native/ServiceApis.cs
index d547ad4..be95d0e 100644
--- a/src/WinSW.Core/Native/ServiceApis.cs
+++ b/src/WinSW.Core/Native/ServiceApis.cs
@@ -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;
diff --git a/src/WinSW/WrapperService.cs b/src/WinSW/WrapperService.cs
index ca339ea..e9ce54f 100644
--- a/src/WinSW/WrapperService.cs
+++ b/src/WinSW/WrapperService.cs
@@ -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? 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,12 +439,17 @@ 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
- if (process.ExitCode == 0)
+ try
{
- this.SignalShutdownComplete();
+ if (process.ExitCode == 0)
+ {
+ this.SignalStopped();
+ }
+ }
+ finally
+ {
+ Environment.Exit(process.ExitCode);
}
-
- Environment.Exit(process.ExitCode);
}
}