@@ -14,14 +14,22 @@ internal class WindowsServiceManager
1414 {
1515 private readonly ILogger < WindowsServiceManager > _logger ;
1616
17+ // Windows Service restart timers after errors.
18+ private const int FirstRestartSeconds = 60 ;
19+ private const int SecondRestartSeconds = 60 ;
20+ private const int SuccessiveRestartSeconds = 86400 ;
21+
1722 /// <summary>
1823 /// Event Log name.
1924 /// </summary>
20- private const string applicationLogName = "Application" ;
25+ private const string ApplicationLogName = "Application" ;
2126
2227 // TODO: validate setter
2328 private string ServiceName { get ; } = "PVBridge" ;
2429
30+ const string ServiceDisplayName = "PVBridge Solar Status Syncer" ;
31+ const string ServiceUser = @"NT AUTHORITY\Network Service" ;
32+
2533 public WindowsServiceManager ( ILogger < WindowsServiceManager > logger , string ? serviceName = null )
2634 {
2735 _logger = logger ;
@@ -64,15 +72,15 @@ internal async Task InstallServiceAsync(IServiceProvider services, string servic
6472 {
6573 if ( ! EventLog . SourceExists ( Program . ApplicationName ) )
6674 {
67- _logger . LogInformation ( "Creating {application} log source {source}" , applicationLogName , Program . ApplicationName ) ;
75+ _logger . LogInformation ( "Creating {application} log source {source}" , ApplicationLogName , Program . ApplicationName ) ;
6876
69- EventLog . CreateEventSource ( Program . ApplicationName , applicationLogName ) ;
77+ EventLog . CreateEventSource ( Program . ApplicationName , ApplicationLogName ) ;
7078 }
7179 }
7280 catch ( Exception e )
7381 {
7482 // That's not a fatal error.
75- _logger . LogError ( e , "Creating {application} log source {source} failed" , applicationLogName , Program . ApplicationName ) ;
83+ _logger . LogError ( e , "Creating {application} log source {source} failed" , ApplicationLogName , Program . ApplicationName ) ;
7684 }
7785
7886
@@ -151,19 +159,16 @@ internal async Task UninstallServiceAsync(IServiceProvider services, Cancellatio
151159
152160 var exitCode = await UninstallServiceAsync ( ) ;
153161
154- if ( exitCode == 0 )
155- {
156- return ;
157- }
158- else if ( exitCode == 5 )
162+ switch ( exitCode )
159163 {
160- throw new InvalidOperationException ( $ "The service \" { ServiceName } \" could not be uninstalled. Exit code: { exitCode } . Run as administrator." ) ;
161- }
162- else
163- {
164-
164+ case 0 :
165+ return ;
166+ // Access denied.
167+ case 5 :
168+ throw new InvalidOperationException ( $ "The service \" { ServiceName } \" could not be uninstalled. Exit code: { exitCode } . Run as administrator." ) ;
165169 // User canceled or process failed, report that to the installer.
166- throw new InvalidOperationException ( $ "The service \" { ServiceName } \" could not be uninstalled. Exit code: { exitCode } .") ;
170+ default :
171+ throw new InvalidOperationException ( $ "The service \" { ServiceName } \" could not be uninstalled. Exit code: { exitCode } .") ;
167172 }
168173 }
169174
@@ -194,13 +199,9 @@ internal async Task UninstallServiceAsync(IServiceProvider services, Cancellatio
194199
195200 private async Task < int > InstallServiceAsync ( string servicePath )
196201 {
197-
198202 var binPath = $ "{ servicePath } service run";
199203
200- const string displayName = "PVBridge Solar Status Syncer" ;
201- const string serviceUser = @"NT AUTHORITY\Network Service" ;
202-
203- var scArguments = $ "create { ServiceName } displayName= \" { displayName } \" start= auto depend= RpcSs binPath= \" { binPath } \" obj= \" { serviceUser } \" ";
204+ var scArguments = $ "create { ServiceName } displayName= \" { ServiceDisplayName } \" start= auto depend= RpcSs binPath= \" { binPath } \" obj= \" { ServiceUser } \" ";
204205
205206 var exitCode = await RunCreateServiceAsync ( scArguments ) ;
206207
@@ -210,7 +211,9 @@ private async Task<int> InstallServiceAsync(string servicePath)
210211 }
211212
212213 // Set failure mode: retry twice after 2 minutes, then after a day. Error count resets in a day.
213- scArguments = $ "failure { ServiceName } reset= 86400 actions= restart/60000/restart/60000/restart/86400";
214+ string restartActionString = $ "restart/{ FirstRestartSeconds * 1000 } /restart/{ SecondRestartSeconds * 1000 } /restart/{ SuccessiveRestartSeconds * 1000 } ";
215+
216+ scArguments = $ "failure { ServiceName } reset= 86400 actions= { restartActionString } ";
214217
215218 return await RunCreateServiceAsync ( scArguments ) ;
216219 }
0 commit comments