Start a windows service without elevation

14,052

Solution 1

I followed torak link and I understand this key difference concerning rights in a service:

  • a service has rights concerning the "Run as" user
  • a service has different permission to control the service (i.e. to start/stop it)

So, to start the service I need to modify the service control permission.

Well, I have done a windows service called Service1 and I made an installer with WIX. During setup I call ServiceInstall

      <ServiceInstall Id="ServiceInstaller" Type="ownProcess" Vital="yes"
       Name="Service1" DisplayName="Service1"
       Description="Service1 description"Start="demand"
       Account="NT AUTHORITY\LocalService"
       ErrorControl="ignore" Interactive="no" >
      </ServiceInstall>

Then I have a client program called TestProgram where I try to start the service:

var service = new ServiceController("Service1");
service.Start();

And obviously it doesn't start the service without elevation of TestProgram (that runs under a normal user account).

So the solution is to instruct WIX to allow members of the user group (for example) to start/stop the service, using the PermissionEx tag:

<util:PermissionEx User="Users" ServiceStart="yes" ServiceStop="yes">
</util:PermissionEx>

Hope this helps. Thank you all.

Solution 2

You can set the ACL for the service itself to allow this. The SetACL.exe utility makes this (somewhat) straightforward; e.g.:

SetACL.exe -on "MyService" -ot srv -actn ace -ace "n:S-1-5-32-545;p:start_stop"

This allows members of the Users group (S-1-5-32-545) to start and stop MyService.

Solution 3

If i can add my 2 cents, here is my solution that wont require any complex App.Manifest or Windows Service modification.

The concept is simply to call "Net Start" through a process that is elevated :

public string StartServiceViaProcess(string param_strServiceName)
    {
        try
        {
            const int ERROR_CANCELLED = 1223; //The operation was canceled by the user.

            Process process = new Process();
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            startInfo.FileName = "cmd.exe";
            startInfo.Verb = "runas";
            startInfo.UseShellExecute = true;
            startInfo.Arguments = "/C net start " + param_strServiceName;
            process.StartInfo = startInfo;
            try
            {
                Process.Start(startInfo);
            }
            catch (Win32Exception ex)
            {
                if (ex.NativeErrorCode == ERROR_CANCELLED)
                    return "L'usager a annulé la demande d'exécution avec privilège.";
                else
                    throw;
            }
        }
        catch (Exception ex)
        {
            return ex.SI_ConvertToString();
        }
        return "";
    }
Share:
14,052
Be.St.
Author by

Be.St.

18+ years experience developing software solutions. Today I'm a software architect with strong knowledge of patterns, testing metodologies, software architecture, source code management, ORM and so on. I'm a trainer, mentor and architectural consultant in several IT companies helping them in change management from waterfall and code and fix style to Agile process and adopting best application lifecycle management practices.

Updated on June 14, 2022

Comments

  • Be.St.
    Be.St. almost 2 years

    I have a windows service "Service1" configured to log on as "Local Service".

    I built a console application to start it programmatically.

            var service = new ServiceController("Service1");
            service.Start();
    

    I know that if I run the ConsoleApplication1 from an administrator command prompt it starts smoothly.

    And if I run it without elevation I get an:

    System error 5 has occurred.

    Access is denied.

    But, I need to start it without elevation.

    Is it possible, or I have to change the way to achieve this?