Reputation: 506
When my service is installed I have a handler that starts the service after it has been installed.
private void InitializeComponent()
{
...
this.VDMServiceInstaller.AfterInstall += ServiceInstaller_AfterInstall;
}
private void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
{
ServiceController sc = new ServiceController("MyService");
sc.Start();
}
I want to stop the service before it is uninstalled so I added an additional handler to InitializeComponent().
this.ServiceInstaller.BeforeUninstall += ServiceInstaller_BeforeUninstall;
and added the function:
private void ServiceInstaller_BeforeUninstall(object sender, InstallEventArgs e)
{
try
{
ServiceController sc = new ServiceController("MyService");
if (sc.CanStop)
{
sc.Stop();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
}
}
catch (Exception exception)
{}
}
But the service doesn't stop before uninstall. Am I using the ServiceController.Stop() function improperly?
Upvotes: 2
Views: 2654
Reputation: 669
I wanted to do something similar, and ended up using this code in my installer project to handle when the BeforeUninstall event was triggered:
private void SessionLoginMonitorInstaller_BeforeUninstall(object sender, InstallEventArgs e)
{
try
{
using (ServiceController sv = new ServiceController(SessionLoginMonitorInstaller.ServiceName))
{
if(sv.Status != ServiceControllerStatus.Stopped)
{
sv.Stop();
sv.WaitForStatus(ServiceControllerStatus.Stopped);
}
}
}
catch(Exception ex)
{
EventLog.WriteEntry("Logon Monitor Service", ex.Message, EventLogEntryType.Warning);
}
}
The custom actions section of the project also had an action to uninstall the primary output of my Windows Service project. This worked for me and has given me a clean uninstall every time I've tested it.
Upvotes: 0
Reputation: 1113
This is the window I tried to prevent:
I have tested all the overrides available, and none of them are executed before the dialog box prompting to close the applications appear.
Not even the class constructor is early enough.
My conclusion is that, as the installer projects are, you cannot stop the service via code, before the dialog box.
Since there are no other ways to have code executed in the project, I don't see any way to accomplish this.
I really really wish it was different, since I badly need this myself, but there just isn't any "hook" available in the installer project, that enters early enough to solve the problem.
My best suggestion, is to make two installers.
One that acts as a wrapper for the second, and on install just starts the second installer as normal.
But on uninstall, it stops the service first, then uninstalls the second.
But this is too much of a hack for my liking, so I have not explored this further.
Upvotes: 0
Reputation: 386
Would something like below help you:
protected override void OnBeforeUninstall(IDictionary savedState)
{
ServiceController controller = new ServiceController("ServiceName");
try
{
if(controller.Status == ServiceControllerStatus.Running | controller.Status == ServiceControllerStatus.Paused)
{
controller.stop();
}
controller.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0,0,0,15));
controller.Close();
}
catch(Exception ex)
{
EventLog log = new EventLog();
log.WriteEntry("Service failed to stop");
}
finally
{
base.OnBeforeUninstall(savedState);
}
}
Upvotes: 1