none
Defining required access rights for a service with ServiceController

    Question

  • Hello,

     

    I'm pretty sure this is straight forward I just can't seem to get it working.

     

    I have a service called serviceX and I want to control it from another application.  The "control" is simply checking the ServiceController.Status field and calling ServiceController.Start().

     

    The exception i get is:-

    System.InvalidOperationException: Cannot open serviceX service on computer '.'. ---> System.ComponentModel.Win32Exception: Access is denied

    --- End of inner exception stack trace ---

    at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess)

    at System.ServiceProcess.ServiceController.Start(String[] args)

    at SnippetCompiler.ServiceMonitor.StartService()

     

    In Win32 I would specify SERVICE_QUERY_STATUS and SERVICE_START as the required access in the OpenService API call.  How do I do this in managed code?  I can only assume I need to use a ServiceControllerPermission object but I can't figure out how.

     

    Keith.

    Monday, April 23, 2007 2:15 AM

Answers

  • Hi Kepboy,

     

    I’ve reproduced and run such code as yours you described above, but I got no exception thrown, I think the most possible reason is that your process haven’t enough right to access the service process.

     

    The .net framework access the service internally using the OpenService API, and it will automatically choose the desired access right code depending on the method you’ve invoked.

     

     For example:

     If you invoke ServiceController.Start();

     It will internally invoke like this: OpenService( serviceManagerHandle, ServiceName, SERVICE_START);  // pseudo code

     Or if you invoke ServiceController.stop();

     It will internally invoke like this: OpenService( serviceManagerHandle, ServiceName, SERVICE_STOP);   // pseudo code

     

     Thanks!

    Monday, April 23, 2007 11:03 AM

All replies

  • Hi Kepboy,

     

    I’ve reproduced and run such code as yours you described above, but I got no exception thrown, I think the most possible reason is that your process haven’t enough right to access the service process.

     

    The .net framework access the service internally using the OpenService API, and it will automatically choose the desired access right code depending on the method you’ve invoked.

     

     For example:

     If you invoke ServiceController.Start();

     It will internally invoke like this: OpenService( serviceManagerHandle, ServiceName, SERVICE_START);  // pseudo code

     Or if you invoke ServiceController.stop();

     It will internally invoke like this: OpenService( serviceManagerHandle, ServiceName, SERVICE_STOP);   // pseudo code

     

     Thanks!

    Monday, April 23, 2007 11:03 AM
  • You're absolutely right.  I wrongly assumed that all users can start services and query the status.  D'oh!
    Tuesday, April 24, 2007 12:20 AM
  • I am facing the same issue, and know it is the access permission issue with ServiceProcess.
    Happens if service run under specified user account which belongs to "User" group. Can check the status of serviec but cannot stop the service.
    Code >>

                System.ServiceProcess.ServiceController _service = new System.ServiceProcess.ServiceController("SERVICENAME");
                if (_service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                        _service.Stop() /// This line throws the error
                       /// Cannot open SERVICENAME service on computer '.'.          System.ComponentModel.Win32Exception: Access is denied System.ServiceProcess
                }


    How will I solve this in C# ?
    Tuesday, May 8, 2007 9:39 PM
  • I'm trying to do the same thing: start and stop a service on a remote computer across domains from an application using the ServiceController class. Is there a good way to do this, like require a local user on the remote computer that has the same username as the user running the app that's calling through the ServiceController class, or is there a way to use the ServiceControllerPermission class to do this? It's not clear from the documentation if the ServiceControllerPermission class is used in the service or in the app that's calling through ServiceController.

    Thanks for any info,
    Richard
    Monday, October 15, 2007 2:53 PM
  • Did anyone find the answer to this, I also found it unclear where ServiceControllerPermission is defined. Is this in the service or the application using the ServiceController... Is there an example anywhere of this...

     

    Thanks,

     

    Robert

    Monday, October 22, 2007 6:29 PM
  • I'm trying to find out if I can grant some permission to the user on the client to be able to start and stop the service.

    So far, I've only been able to do it if the user is in the Administrators group on the server machine.

    Richard
    Tuesday, October 23, 2007 7:30 PM
  • I am having the same problem.  The "Answer" above is confusing.  I don't know what permissions/access right code is required to allow my users to remotely use the ServiceController. 

    Can anyone outline for me exactly what is required for a user to have access to ServiceController and manage a remote service?  Making my users administrators is not an option.

    Also, note that I'm getting the exception on the Status property of the ServiceController object.  For example:

    Dim service As New ServiceController("SERVICENAME", "MACHINENAME")
    Dim status As ServiceControllerStatus = service.Status ' //Exception is thrown here!


    Thanks.
    Thursday, October 25, 2007 1:22 PM
  • I was able to do this using security templates on the server to give the user access to the service without adding the user to the administrators group: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sys_srv_permissions.mspx?mfr=true

    I have an agent running on the server though that does some configuration, and I realized that the best thing for me to do is to move the ServiceController code to that agent and then I don't have the permissions problem.
    Monday, November 5, 2007 4:19 PM
  • You need SERVICE_QUERY_STATUS permission on the Windows service.

    You can do this two ways:
    1. using the subinacl utility to grant permission on the service
    2. using managed code from stackenbloggen: I've written about some of the gotchas.

    Comments on my blog are welcome!

    Craig
    Tuesday, March 11, 2008 5:47 PM
  •  

    Hi guys here also the same problem .
    i tried the same service controller it works perfectly with XP machine.
     but in the case of windows server 2003 sp2 (don't know about sp1 case)

    log is here

    LogType:ErrorMessage ErrorMessage:Cannot open Servicename service on computer 'Competername'.;InnerExcpetion:Access is denied ExceptionDetails:   at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess)
       at System.ServiceProcess.ServiceController.Start(String[] args)
       at System.ServiceProcess.ServiceController.Start()
       at ListenerServicesManagement.startService(String serviceName, String machineName, String userName) InnerException:System.ComponentModel.Win32Exception: Access is denied UserName:admin LogTime:1/12/2009 4:55:48 PM 


    Can anyone help about this issue.....

    Monday, January 12, 2009 11:35 AM
  • The service controller won't work on win7, vista, 2008 etc... Our .net apps get "access denied" error. Is there no solution to this?

    this is not an auto signature. I type this at the bottom of every email I send.
    Thursday, March 4, 2010 4:36 PM
  • I am running Vista and had the same problem exactly but found it was a result of the service name used.

     

    E.g. to get status of SQL service I used “sqlservr.exe” which resulted in Access denied error.

    But if I right click on the service from the Windows services tab and select properties I can see the actual “Service Name” in this case “MSSQL$MIKES” and then use this name it works no problem.

     

     

    Saturday, April 10, 2010 2:51 AM
  • Greetings,

    I had a situation like this.
    I had a service1 which is to check on another service2, is 'Running' or 'Stopped'.
    If Service2 is 'Stopped' start the Service2.

    My code was running correct. I had faced acces deny error when i tried to start the service2.
    All i have to do (other that making the code correct) use a ServiceController,
    ServiceController.Service2.Start();

    And most importantly.Changed the properties of the  Service1 to Administrative account.
    Rightclick on the property(in Services.msc panel)..select the Log on option.
    Change it to Local Account.
    You are done.

    Good luck guys.
    I hope this will help some of you.

    Tuesday, November 23, 2010 11:37 AM
  • This does not work for me I get "at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess)" The services in the registy are set to local account but it is me ( a user ) who is running the program ( http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.aspx ) or rather a variation of that checking for pause / continue properties.

    Clearly if I open a dos/cmd window run as administrator it works, if I run it as me it does not work.

    When I goto the control panel vista asks me for "User Account" permission before I can enter the services screen, So how do I 'grant' 'rights' with something like:

     public System.ServiceProcess.ServiceControllerPermissionEntry(
     ServiceControllerPermissionAccess permissionAccess,
     string machineName,
     string serviceName
    ) with ServiceControllerPermissionAccess.Control to the running ServiceController ?

    Back in 1997 under Windows NT with Win32 the following worked and yes it works today in the debug version of Visual Studio 6.0 and the release version if run in the IDE

    void CDisplayView::OnServiceStart()
    {
     SC_HANDLE  hSCM     = NULL ;
     SC_HANDLE  hService = NULL ;
    // SERVICE_STATUS ss ;
     BOOL   b ;
     HTREEITEM       h = m_TreeCtrl.GetSelectedItem() ;
     CString         s = m_TreeCtrl.GetItemText( h ) ;

     if ( (hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS )) != NULL ) 
     {
      if ( (hService = ::OpenService( hSCM, s, SERVICE_ALL_ACCESS )) != NULL )
      {
    //   ::ZeroMemory( &ss, sizeof( ss ) ) ;
    //   if ( (b = ::QueryServiceStatus( hService, &ss )) == TRUE )  
    //   {
    //    if ( ss.dwCurrentState == SERVICE_STOPPED )   
    //    {
         if ( (b = ::StartService( hService, 0, NULL )) == TRUE )
         {
          m_TreeCtrl.SetItemImage( h, m_id_Green, m_id_Green ) ;
          m_bIsStarted = TRUE ;
         }
    //    }
    //   }
       b = ::CloseServiceHandle( hService ) ;
      }
      b = ::CloseServiceHandle( hSCM ) ;
      Sleep( 2000 ) ;
     }
    }
    This works because of _ALL_ACCESS, What I am doing is translating/re-writing my very old c++ program in c# Express 2008 with 3.5 assemblies.

    any ideas would be appreciated, cheers!  


    Darren Webb
    Friday, March 4, 2011 9:58 PM
  • You can assign permissions to a user to be able to restart a specific service. I've done this using Group Policy.
    http://support.microsoft.com/kb/256345?wa=wsignin1.0

    This article may also be useful:
    http://serverfault.com/questions/187302/how-do-i-grant-start-stop-restart-permissions-on-a-service-to-an-arbitrary-user

    Friday, October 26, 2012 7:45 PM
  • This may not be the most elegant solution, but you can use WMI. There are many examples on the internet that can get you started. It gets tricky with restarting services as there is no function (that i know of) that queries that status of the service so i had to write my own check. I gave the users specific permissions to be able to restart the services.
    Friday, October 26, 2012 7:51 PM
  • Sunday, August 4, 2013 10:30 PM