0

The design of the current app I'm working on calls for a WCF Service, hosted in a Windows Service, that pulls data and stores it on the hard drive. It pairs with a windows forms application that will interact with the WCF Service. One of the requirements is that the end user be able to restart the windows service through the Forms app.

So, I'm guessing this can be done using the ServiceController class... but what about permissions? I don't think we can (or should) guarantee that the windows app runs as admin, and the service is running as a Network Service.

The only thing I've seen that reasonably seems to cover the situation is having another windows service running, which could then be installed under an account with higher permissions, which you could call to restart the target service.

BUT I don't want to add that much complexity to the project, especially since it was supposed to be in beta last week.

So is there a way I can just give the Forms app the necessary permissions to restart it's specific companion service?

The follow-up question is down the line we might make it so the service runs on a server rather than the same machine as the app. Would this make it impractical to allow a Forms app to restart the service? If so I may advocate cutting the feature...

Oh, and should note that the target platforms are WinXP and Win7 with .NET4.

CodeRedick
  • 7,346
  • 7
  • 46
  • 72

2 Answers2

1

Instead of giving permissions to the app, you can assign permissions to the service to be started and stopped.

Every windows service has a security descriptor that is assigned a permissions what you are allowed to do on the service. By default service has permissions for authenticated users to read services state, and for admins to control the service, as well as delete it.

You can set service security descriptor using command sc sdset <serviceName>. For example this command will allow any user to control service (but only admins and Local system are allowed to delete service or change security on the service):

sd sdset <myservice> "D:(A;;CCLCSWRPWPDTLOCRSDRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)"

You might want to tweak the security descriptor a bit if you want to allow only a specific account to be used to control the service. This would work remotely as well, as long as the remote account is authenticated by the machine.

seva titov
  • 11,720
  • 2
  • 35
  • 54
  • This is the right approach, but it is easier to set permissions on a service with SetACL. Here is an example: http://helgeklein.com/setacl/examples/managing-printer-service-and-share-permissions-with-setacl-exe/ – Helge Klein Mar 21 '12 at 08:49
0

How about making the service responsible for restarting itself? It could expose a method, Restart(string userId, string password) or something similar.

On being called by an authorised user, it could use the approach outlined in this answer. That is:

  1. Set the service to restart on failure
  2. Call Environment.Exit(1)
  3. OS restarts the service for you.

You would call Environment.Exit(0) if didn't want to restart.

Community
  • 1
  • 1
Steven P
  • 1,956
  • 1
  • 16
  • 17