service
service copied to clipboard
Propagate windows service start parameters
This library simply ignores and doesn't propagate the start parameters of windows services.
Those live parameters are very convenient and flexible, allowing to avoid configuration files or registry keys to store the parameters.
Related to #75
A new method (e.g. Args() []string
) could be added to Service
without breaking backwards compatibility.
Would you be interested in a PR?
The Start()
method should also pass the arguments (and that one is tricky to change without breaking backwards compatibility)
Are the args passed into Execute different then os.Args()?
Yes, Windows seems to distinguish between:
- The arguments (
os.Args()
) passed to the Service Application binary managing services - The arguments (provided by
windows/svc.Execute()
) passed to a service on start.
AFAIU the arguments passed to Execute()
are the ones provided to StartService (from advapi.dll
)
As an example, both sc.exe
and the Services UI let you pass those arguments on start:
$ sc.exe start
DESCRIPTION:
Starts a service running.
USAGE:
sc <server> start [service name] <arg1> <arg2> ...
The following WinRM command responded with a non-zero exit status.

Note that, in the last example you are free to choose service start arguments different from the ones passed to the binary (-k netsvcs
)
@kardianos I got the problem too.
First, when I run my code with go run
, it works correctly:
The first two line print by
fmt
, execute before service start.
The other print by log
, witch would redirect to log file in service mode.
However, when I run my code with builded binary executer, the problem appeared:
You can see that
fmt
print the os.Args
correctly, while log
missing them.
Any news about this? Something like what @2opremio proposed would be really nice to have :-)
Oh, we can already manually propagate arguments! Sorry about the noise...
I ended up using something like:
nameFlag := flag.String("name", "dummy", "Service name.")
flag.Parse()
s, err := service.New(
&dummyService{},
&service.Config{
Arguments: []string{"-name", *nameFlag},
Name: *nameFlag,
DisplayName: "Dummy Windows Service",
Description: "Dummy Windows Service",
})
Can this technique of passing arguments be used to say create a "Delayed" start service?
Yes.
Oh, we can already manually propagate arguments! Sorry about the noise... &service.Config{ Arguments: []string{"-name", *nameFlag}, })
@rgl , does this example actually propagate the live argument as @2opremio called out? And how to access this parameters from the actual service start method when the parameter not passed through executable but through sc.exe or service control manager?
I did more investigation, and see adding a line of ws.Arguments = append(ws.Arguments, args...) in Execute method of service_windows.go solved the issue for me.
func (ws *windowsService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
changes <- svc.Status{State: svc.StartPending}
ws.Arguments = append(ws.Arguments, args...)
then in my usage, I declare service.Config to my program struct, and then in program Start method access the parameter from p.config.Arguments, and I've validated that could propagate the live arguments from service control manager.
@kardianos , how do you feel this solution?
@chuanbozhang-okta @kardianos @rgl Is support for runtime arguments like below supported in windows service start method?
sc start serviceName arg1 arg2 ... argN
to be explicit when a customer starts the service with a runtime port number, I need to access this runtime parameter somehow or injected somhow.
sc start MyGrpcService runtimePortNumber
@msays2000 , yes, my proposal fix above to add "ws.Arguments = append(ws.Arguments, args...)" to Execute method could fix the issue and make your usage work.
@kardianos , do you accept contribution for this? If so I could send a PR for it.
@chuanbozhang-okta thank you for confirming. @kardianos please review and help in merging the above PR of @chuanbozhang-okta
We have a use case where we need to start a grpc service on a determined port passed to the service via its start arguments.
@kardianos is there an alternative to pass the arguments to a service.