(#13489) Synchronously start and stop services
Previously, we were using the win32-service gem to start and stop
services. It uses Win32 APIs to programmatically send start and stop
requests. The actual service starts/stops asynchronously with respect
to the request. As a result, when refreshing a service, puppet would
issue a stop request, immediately followed by a start request, and that
would race as the service would often still be running when the start
request occurred, leading to 'An instance of the service is already
running'.
This commit changes the windows service provider to use net.exe to
start and stop services. This command will block until the service
start/stops, and returns 0 on success, making it easy to adapt to the
provider command pattern. The one downside is that the exit codes don't
have the same resolution that we can get via the sc.exe or by calling
the Service Control Manager programmatically. But that is not too
critical because we do capture the output of the net.exe command, e.g.
'The service name is invalid.' and include it in the exception message.