简体   繁体   中英

Programmatically grant local user rights to start a service with .Net

I want to implement an update service in my application (so users don't need admin rights to update my app once the service is installed, much like Google or Mozilla do their updates), and I think I found a good way to do this with WCF.

I have a WCFServiceLibrary -Project which contains the ServiceContract and the core functionality (download/install updates) and a Windows Service-Project which implements the WCFServiceLibrary as a Windows Service. Additionally, there is a Visual Studio Installer -Project which installs the service and my application, which should be able to start/stop/communicate with the service using NamedPipes.

The service is configured to start manually with the LocalSystem-Account. Now when the service is installed, I can start/stop it using services.msc (probably elevated), but not when I try it with net start Servicename (Error 5: Access denied) or with my application, which tells me that the local users probably don't have the permission to start/stop the service.

I need the service to run with higher permissions in order to perform the installation of updates, so I would like to give local users permission to start my service either during the first installation of the service or when the service starts for the first time (since I can trigger that also during installation).

However, how would I accomplish this with VB.NET (or C#)? I found some examples using API-Calls of advapi32.dll, but it didn't looks like the permission can be changed with this.

So, long story short, heres a summary of what I'm looking for:

  • Grant Group "Local Users" permission to Start my Service, best approach either during installation (Maybe with Custom Actions in Visual Studio Installer Project? Or in the ServiceInstaller-Class in the Windows Service-Project?) or the first time the service starts (OnStart-Event in Windows Service Project)
  • The service must not run with local user rights, since it would miss elevated privileges then which would be necessary to install updates.
  • I can't assign permissions through GPO/Local Policy since the users are not within our company, but all around the world. For the same reason I cannot assume that they can get an admin to elevate them everytime an update comes out.
  • I would like to avoid commandline calls if possible (as in assign permissions through command line, since those are most likely os-dependent)
  • Another solution would be to configure the Service as Automatic and Start it after install, but I don't like the idea that my service runs all the time since its only needed when my main application starts up.
  • Its most likely not a file permission issue. EVERYONE, SYSTEM and SERVICE got FULL ACCESS to the services folder and files in it.

There are already different similar questions here, but none did give a clear answer to this problem. One user probably did it using the WiX-Installer, but I would like to keep the Visual Studio Installer Project since it's pretty straight forward and easy to use.

After a bit more of googling and trying to find a "clean" solution, I've given up and using now Process.Start to execute sc.exe and set new Permissions after Installation.

Here's my ServiceInstaller-Class, for anyone curious:

[VB.NET]

Imports System.ComponentModel
Imports System.Configuration.Install
Imports System.ServiceProcess

<RunInstaller(True)>
Public Class SvcInstaller
    Inherits Installer

    Dim svcprocinst As ServiceProcessInstaller
    Dim svcinst As ServiceInstaller

    Public Sub New()
        svcprocinst = New ServiceProcessInstaller
        svcprocinst.Account = ServiceAccount.LocalSystem
        svcinst = New ServiceInstaller
        svcinst.ServiceName = "KrahMickeySvc"
        svcinst.DisplayName = "Mickey-Service"
        svcinst.Description = "This Service is used by KRAH Mickey for application updates and maintenance"
        Installers.Add(svcprocinst)
        Installers.Add(svcinst)

    End Sub

    Private Sub SvcInstaller_AfterInstall(sender As Object, e As InstallEventArgs) Handles Me.AfterInstall

        'Set new permissions acc. to Security Descriptor Definition Language (SDDL)
        'Source: https://blogs.msmvps.com/erikr/2007/09/26/set-permissions-on-a-specific-service-windows/
        'Keeping the source DACL and just adding RP,WP and DT (Start/Stop/PauseContinue) to IU (Interactive User)

        Dim DACLString As String = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRCRPWPDT;;;IU)(A;;CCLCSWLOCRRC;;;SU)"
        process.Start("sc.exe", $"sdset {svcinst.ServiceName} ""{DACLString}""")


    End Sub

End Class

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM