Question

This is a long post, so here's the meat of my question up-front: I'd like to use the ServiceController class in C# to control services on another computer, but it looks like I need to impersonate an account on the service host computer to comply with how .NET manages security. How do I do that?


The details:

We have some WCF services hosted on a server and a client app that depends on them. (Everything is written in .NET 4.0 C#.) There is a dashboard on the client that shows which services are working, and if any of the services go down, we would like to let users try to remotely restart them. After some research, it looks like ServiceController can do what we're hoping for. I've started playing around with it, and this is what I've written so far:

/// Called when the user clicks a button in the system health dashboard view
///to restart a broken service
private void RestartService()
{
    var servcntrls = ServiceController.GetServices(HostName);
    //TODO finish method
}

Obviously, this doesn't actually restart the service. I think I see how to do that using ServiceController.Start() and .Stop(). When just this much code is executed, though, an exception is thrown when GetServices() is called:

Type = System.InvalidOperationException
Message = Cannot open Service Control Manager on computer '/* computer name snipped */'. This operation might require other privileges.
Data:
System.Object = 

Stack Trace:
at System.ServiceProcess.ServiceController.GetDataBaseHandleWithAccess(String machineName, Int32 serviceControlManaqerAccess)
at System.ServiceProcess.ServiceController.GetDataBaseHandleWithEnumerateAccess(String machineName)
at System.ServiceProcess.ServiceController.GetServicesOfType(String machineName, Int32 serviceType)
at System.ServiceProcess.ServiceController.GetServices(String machineName)
at Client.Organizer.SystemHealth.ViewModels.ClientStatusViewModel.RestartService() in C:\Source\X\Trunk\Client\Organizer\SystemHealth\ViewModels\ClientStatusViewModel.cs:line 38
at GalaSoft.MvvmLight.Command.RelayCommand.Execute(Object parameter)
at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
at System.Windows.Controls.Primitives.ButtonBase.OnClick()
at //Snip

==== Inner Exception ====
Type = System.ComponentModel.Win32Exception
Message = Access is denied

I did some research into this and found these threads:
How to remotely control a Windows Service with ServiceController?
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/18c34a5c-8637-4e85-b9ee-d9052bb12a34/
ServiceController permissions in Windows 7
servicecontroller permissions
http://social.msdn.microsoft.com/Forums/en/wcf/thread/c35e75c4-de7d-409d-bc82-4533e4982264

What I've gathered from them is that when ServiceController interacts with services, it needs to have the proper permissions to talk to them. The articles I found suggested impersonating a user account with the appropriate privileges on the server.

Unfortunately, I am completely new to how .NET manages security concerns, so I don't know how I'd go about that. So here are my questions:
1. Is impersonating an account on the server an appropriate approach to this problem? One person in the threads I read thought it raised too many security vulnerabilities.
2. How can I impersonate an account? Is there an article somewhere with a good code example?
3. Is there some way to impersonate a user without configuring the server and the client computers? We set up our system in our clients' environments, and I don't want to add an obscure step to installation.

EDIT: Our WCF services are hosted as windows services, as per AvkashChauhan's answer.

Was it helpful?

Solution

A WCF service can be hosted on 1) an IIS Web Server, 2) WAS server, 3) Self Host and finally 4) Windows Services and if your WCF service is hosted on Windows Services only then you can use ServicesController class to control the service. While IIS and WAS based WCF service provide control through app domain and process however a Windows Service Hosted WCF service is managed via ServiceController class.

I just want to be sure that your WCF service is hosted as Windows Service because It is not clear in your questions. The link above are mostly handling a Windows Service (not a WCF Service).

Also you can host WCF service as Windows Service via HTTP/netpipe or other ways so depend on what communication channel you have used, the security settings will be based on that so do you know what is it?

With WCF service you would can try first use IP address instead of Machine Name to Get hosted service first as this is very common problem. Also check out the following SO discussions:

WCF: StackoverFlow exception

Windows Service hosted WCF over HTTPS

OTHER TIPS

you can use in your tool

PsExec Tool in order to execute a command-line process on a remote machine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top