Having trouble replacing mix release files on Windows when installed as a service

Hi everyone, I’ve been having some issues updating an app built with mix release after it was installed as a service on windows.

Normally I would stop the app, replace the files, and start it up again. Zero downtime isn’t a requirement here. But now that it’s installed as a windows service, it won’t let me replace the release files even after I’ve stopped the service. It tells me the files are open, so I’m assuming something is still running even though the service is stopped.

I’ve also tried uninstalling the service before, thinking I might need to do that first, but there seems to be an issue with that too for me. It’ll say that it’s uninstalled, and will be removed from the services list, but if I try to install a new version it tells me that service is already installed (despite that I uninstalled it). I’m guessing this is some windows peculiarity.

Any help would be greatly appreciated!

I used InnoSetup to handle install and uninstall when shipping elixir app as windows service. An upgrade is equivalent to uninstall old version and then install new version. I’m guessing InnoSetup does some additional work with the registry, either way it ensures when you uninstall the program, it really is completely uninstalled and the files are deleted.

Thanks for the tip! That does look like a good way to do it, though I have no real idea how to use it yet. Is it difficult to configure?

Any chance you’d be willing to write a short guide somewhere, since you’ve done it :sweat_smile:? This seems like it would be a really useful guide to have for lots of people. If not, I’ll see if I can figure it out and write a guide after.

Here are the most important bits for Inno Setup to build the installer

#define MyResourceDir "C:\path\to\build\output"

[Setup]
PrivilegesRequired=admin

[Files]
Source: "{#MyResourceDir}\myapp\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Run]
Filename: "{app}\bin\myapp.bat"; Parameters: "install" ; Flags: runascurrentuser
Filename: "{app}\bin\myapp.bat"; Parameters: "start" ; Flags: runascurrentuser

[UninstallRun]
Filename: "{app}\bin\myapp.bat"; Parameters: "uninstall" ; Flags: runhidden

[Code]
// install vc2013 32bit or 64bit depending on erlang
// vcredist2013('12');

In addition, I modify myapp.bat script a bit to change service description and firewall, but that’s optional.

Hopefully that helps!

2 Likes

That’s awesome, thank you!

The only thing I’m unsure about is how to include or package up the release files with inno Setup. The script uses an absolute path for MyResourceDir, so the person installing this would need to have those files available at that location? Inno Setup doesn’t bundle them in and place them there or anything, right?

Inno Setup makes an installer exe for you, so yes it bundles files and extracts them to desired installation directory, it also registers the program with Windows so you can uninstall it from the control panel. Inno Setup has been around for a while, it uses Pascal script, while it is not the nicest installer creator out there, it gets the job done and is freeware.

1 Like

Thank you so much, this has been really, really helpful.

Alright, so I’ve tried out InnoSetup, which seems great. I’m still running into the same issues revolving around the way that Elixir releases are installed on Windows though.

The problems seem to be:

  1. The service that gets created will be named myapp_myapp (replaced with your apps name), and the service DISPLAY name will be that, but the actual service name will be something like myapp_myapp34is3hjfk. This is a problem because…

  2. When I uninstall using the release uninstall command (myapp.bat uninstall) it seems to remove that service, but doesn’t actually remove it completely. That is, it’ll disappear from the windows services list, but If I try to reinstall, it’ll say a service with that name already exists and fail. Uninstalling with innosetup has the same result (since it uses the uninstall command under the hood anyways)

  3. There are ways to remove partially uninstalled windows services, but they all require you to know the REAL service name, like I mentioned in point 1. Unfortunately, after using myapp.bat uninstall command, that service disappears from the list and I haven’t found a way to actually find the real service name instead of just the display name once it’s gone from that list. Sometimes restarting the machine entirely will finish uninstalling the service, but not always. Requiring a full restart to update the elixir release is also a problem for my use case at least, as other critical apps are running on that server and that would take them down far too often.

  4. epmd.exe seems to always be running. When I try to reinstall using inno setup, I can’t complete it because epmd.exe is running. It doesn’t show up in the task manager or the services list. I can’t just delete and replace the release files, then restart to update the app, because empd.exe is running. I can’t shut it down because it doesn’t show up in any processes or services list. Very confusing.

So I suspect if I can shut down epmd when I stop or uninstall the app, I could easily update and just keep the same service. But for whatever reason it seems to never shut down or be listed as a running process.

Edit: After downloading something called process explorer (from micrososft, but not installed by default), epmd.exe shows up as a process in there but not task manager :expressionless:. If I close it there, I can replace the files. Overall, it feels very much like using elixir releases as a windows service is extremely brittle if you ever need to update or uninstall it. It seems like the issues lie mainly in the way that erlsrv handles services, though I’m not sure where it’s going wrong.

Distillery sets service name like so https://github.com/bitwalker/distillery/blob/master/priv/libexec/commands/win/install.ps1#L7, service name must be '<nodename>_<release vsn>'.

I know exrm is totally out of date but it was a simple enough tool to build releases. Once exrm builds the release, there is a batch script at rel/myapp/releases/<ver>/myapp.bat. I suppose Distillery generates a similar file? Anyhow, in myapp.bat, look for the line starting with @set service_name then replace with a nicer name like @set service_name="My Fancy Server". The batch script generated by exrm works on Win 7/8/10, and Server 2016.

I’m pretty sure if service name remains static things will work. This shouldn’t too hard. I’ve had more interesting problems like running 32bit and 64bit C nodes at the same time.