1
votes

I have a Windows Service built with Delphi 2010, and I'm using a Inno Setup installer for deployment.

It's mostly working smoothly - I correctly stop the service before uninstalls and upgrades, and restart it following installs.

[Run]
Filename: {app}\MyService.exe; Parameters: "/INSTALL /SILENT"; ...

[UninstallRun]
Filename: {app}\MyService.exe; Parameters: "/UNINSTALL /SILENT"; ...`

However, I have one problem left: If I run the installer twice in succession, then the next time I uninstall it fails showing a Message Dialog : Service XXX failed to uninstall with error: "System Error. Code:1060. The specified service does no exist."

Logging shows that the "UninstallRun" section is being executed twice when the uninstaller runs. And the second time, it fails and throws the error message (from TServiceApplication::RegisterServices) because the service is already uninstalled. Pretty sure this is because of the way Inno Setup tracks multiple installations in uninstall.dat.

My 'hack' to fix this is to use the TService's ServiceBeforeUninstall handler, and exit(0) if the service isn't installed. This feels like a brute force approach - is there a smarter way of resolving the problem?

1
I agree that Inno should not be triggering the Uninstall logic multiple times, but I would also consider this to be a logic bug in TService, too. Apparently Borland (then CodeGear, then Embarcadero) never thought to update UninstallService() to ignore ERROR_SERVICE_DOES_NOT_EXIST before raising an exception. If a service is being uninstalled and it does not exist, that should not be a failure condition, the intended result is already true. - Remy Lebeau
BorCoDero has been updating the SvcMgr unit over the years with only very minimal code changes to account for OS/compiler/RTL breakages, not to fix logic errors, or add new features that have been repeatedly requested. Oh well. - Remy Lebeau
Read about RunOnceId in InnoSetup docs if you want run some unistall entries only one after several installations. jrsoftware.org/ishelp/index.php?topic=runsection However it won't fix all scenarios, as service can be uninstalled by user/other apps. - Krystian Bigaj

1 Answers

1
votes

Don't use the built-in SCM wrapper functions in TService, use the SCM API, they will give you much more control on service management. I wrote an InnoSetup script years ago, you can find it here - it's a while I don't update it, but it is still a starting point.