go-msi
go-msi copied to clipboard
Add support for windows services
In many (or at least some) cases, golang binaries will work as a daemons executing 24/7
It would be great if the manifest was extended to define services. These services would be started automatically upon installation and stopped/removed on uninstallation.
Alternatively, we do this manually, but for that we need #2
Hi,
after some researches and according to my current understanding, services can be installed via a wix declaration within the wix file.
See this example, The most interesting part is,
<!-- The files inside this DirectoryRef are linked to the Test Service directory via INSTALLFOLDER -->
<DirectoryRef Id="INSTALLFOLDER">
<!-- Create a single component which is the TestService.exe file -->
<Component Id="$(var.TestService.TargetFileName)">
<!-- Copies the TestService.exe file using the project reference preprocessor variables -->
<File Id="$(var.TestService.TargetFileName)" Source="$(var.TestService.TargetPath)" KeyPath="yes" />
<!-- Remove all files from the INSTALLFOLDER on uninstall -->
<RemoveFile Id="ALLFILES" Name="*.*" On="both" />
<!-- Tell WiX to install the Service -->
<ServiceInstall Id="ServiceInstaller"
Type="ownProcess"
Name="TestService"
DisplayName="$(var.Name)"
Description="A Test Service that logs dummy text on an interval to a text file."
Start="auto"
ErrorControl="normal" />
<!-- Tell WiX to start the Service -->
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="TestService" Wait="yes" />
</Component>
</DirectoryRef>
Where ServiceInstall must be within a Component and those little thing,
The service executable installed will point to the KeyPath
for the Component. Therefore, you must ensure that the
correct executable is either the first child File element
under this Component or explicitly mark the appropriate
File element as KeyPath='yes'.
See also the File.KeyPath property,
Name | Type | Description | Required |
---|---|---|---|
KeyPath | YesNoType | Set to yes in order to force this file to be the key path for the parent component. | - |
The ServiceControl already defines setup/uninstall behaviors.
Then compare with the current template here, under this Directory node, there should be a new component node to define services.
One bogus thing, the File node of the ServiceInstall will be declared twice in one to many ways
- The service files are explicitly declared as a File node twice
- The service files are declared as both File for the service definition and as a regular file being part of a Directory
Does it matter any how ? Will Wix complain or misbehave ?
Next step is to work on the schema update of the file config, https://github.com/mh-cbon/go-msi/blob/master/wix.json New fields needs to be created to update the templates so new services can be created.
Note how a service file might end up being declared twice in files and (the tbd) services sections, if that should happen, it would be great to find an elegant way to get ride of this duplication, its an easy source of error.
I d familiarize with the demo to
use it as a sandbox to better understand the behavior of Wix.
Usually i run it once, then i update the code, then i run vagrant rsync
, then i re build and re run the setup starting at the section # generate the build
Then just code the update in a new PR,
the code is straight forward (except the way wix works),
make use of generate-templates
subcommand to develop.
This update should not break api.
For reference, check also, http://www.schiffhauer.com/wix-template-for-installing-a-windows-service/
Given the existence of the ServiceInstall node it is not needed to involve a bat file to setup a service, imho.
That s it!
Thanks for the detailed description!
However, after further digging, since:
- Services can be easily created by
sc create
or even from Go itself. - I need installation hooks for other purposes.
I am thinking of simply implementing #2 and invoking sc.exe
during installation to register the service.
As an alternative to invoking sc.exe
, I am considering to implement a register
subcommand in my program, like postgres does with pg_ctl register, and do the registration from Golang instead.
yes, this or that, i m happy to see this feature enhanced based on use cases that helps me to decide what s best.
but great idea for sure.
I stumbled across this issue today and I'm glad I did. I was planning on using it to install windows services in the coming weeks and hope it's possible by the time I get there. I'd suggest avoiding the scripting method with sc.exe if we can get this to work. I wrote a program in AutoIt in 2004 which essentially automated the ancestors of sc.exe from the Windows SDK and turned any .exe into a system service. It worked but was always a hack. It worked on Server 2003 and XP, but doubt it works today. Hopefully we can get the go-msi schema modified to support this.
https://github.com/solvingJ/simpleservice-win-au3
@solvingj i m not very clear about AutoIt and how that works, nor what it requires prior to run.
To go further, in any cases, i suggest to demonstrate the changes to apply to this demo program to install it as a service using this/or/that solution.
In my experience windows service are painful to implement because the implementation needs to be aware. it is intrusive, yet necessary for fine grain response of the application to the os messages.
Yeah, the AutoIt thing isn't helpful to us here. I don't know what the solution is, will have to look into it further.