mullvad / windows-service-rs

Windows services in Rust
Apache License 2.0
485 stars 79 forks source link

add testing utilities #122

Open danieleades opened 3 months ago

danieleades commented 3 months ago

i'm finding the development loop pretty challenging while creating a service. That's probably on me for the most part- i'm very new to this framework.

Here's what i'm doing now-

  1. making code changes using a non-elevated process
  2. opening an elevated command prompt
  3. running 'install_service' example from elevated prompt
  4. launching windows services as admin
  5. starting service
  6. stopping service (checking for clean shutdown)
  7. running 'remove_service' example from elevated prompt

that's pretty painful to be honest, when all i really want is a semi accurate mock of the service manager to start my service entrypoint, wait a second or so and then stop it again.

Is there a better approach i should be using? Or should this library provide a service manager mock for testing purposes?

pronebird commented 3 months ago

I think it's enough if you simply install the service once, mark it on-demand so the system doesn't autostart it. So then you don't have to repeat steps 3 and 7 on each build which is tedious.

Then perhaps automate your flow using scripts or command aliases, i.e:

runas /user:admin net stop <my_service>
cargo build
runas /user:admin net start <my_service>

I am not sure if runas is gonna be pleasant to use, worst case a separate shell with admin rights would do it, there is also windows-sudo and elevate.exe and many other ways to run something with elevated perms on windows so I think something can be done.

Although I think I used to run cargo build and all that as admin and that was fine for development purposes. When you're done you have to wipe the target/ to prevent permission issues once you're back to building as a regular user.

Since there is no stdout in window services, I'd typically make windows service log to file and then stream it with some of unix tools like tail in a separate terminal or split terminal:

tail -F log.txt
danieleades commented 3 months ago

@pronebird thank you that's a big help. I'd assumed the 'install_service' was copying the binary somewhere else, but if i can just rebuild it in place that makes things a lot easier.

I'm logging to a file in order to see what's happening, but i'm finding any logging within the control command event handler isn't firing. Should i expect logging to work there? see https://github.com/danieleades/grpc-service/blob/main/src/main.rs and https://github.com/mullvad/windows-service-rs/issues/116#issuecomment-2027432171

pronebird commented 3 months ago

@danieleades No it's doesn't copy it anywhere and this can be verified by locating your service in Services pane on Windows, or using the SC utility tool to print out the service entry:

sc qc grpc-service

For creating a service manually with admin shell, you can use the following command:

sc create grpc-service binPath=C:\Users\<user>\grpc-service\target\debug\grpc-service.exe type=own start=demand

(you have to fix the absolute path to binary)

Then to delete the service:

sc delete grpc-service

In regards of your program, I am not quite sure why you don't receive the events.