以编程方式授予本地用户权限以使用 .Net 启动服务

Posted

技术标签:

【中文标题】以编程方式授予本地用户权限以使用 .Net 启动服务【英文标题】:Programmatically grant local user rights to start a service with .Net 【发布时间】:2018-07-22 14:01:25 【问题描述】:

我想在我的应用程序中实现更新服务(这样用户在安装服务后就不需要管理员权限来更新我的应用程序,就像 Google 或 Mozilla 进行更新一样),我想我找到了一个好方法使用 WCF 执行此操作。

我有一个 WCFServiceLibrary-Project,其中包含 ServiceContract 和核心功能(下载/安装更新)和一个将 WCFServiceLibrary 实现为 Windows 的 Windows Service-Project服务。 此外,还有一个 Visual Studio 安装程序-项目,用于安装服务和我的应用程序,它应该能够使用 NamedPipes 启动/停止/与服务通信。

服务配置为使用 LocalSystem-Account 手动启动。 现在安装服务后,我可以使用 services.msc (可能已提升)启动/停止它,但当我使用 net start Servicename (错误 5:访问被拒绝)或我的应用程序尝试它时不能,这告诉我本地用户可能没有启动/停止服务的权限。

我需要以更高权限运行该服务才能执行更新安装,因此我想授予本地用户权限以启动我的服务,在第一次安装服务时服务第一次启动时(因为我也可以在安装过程中触发)。

但是,我将如何使用 VB.NET(或 C#)来实现这一点?我找到了一些使用 advapi32.dll 的 API-Calls 的示例,但看起来权限不能用这个来更改。

所以,长话短说,以下是我正在寻找的内容的摘要:

授予组“本地用户”权限以启动我的服务,最好的方法是在安装期间(可能在 Visual Studio 安装程序项目中使用自定义操作?或者在 Windows 服务项目中的 ServiceInstaller-Class 中?)或第一次服务启动(Windows 服务项目中的 OnStart-Event) 该服务不得以本地用户权限运行,因为它会错过安装更新​​所必需的提升权限。 我无法通过 GPO/本地策略分配权限,因为用户不在我们公司内,而是在世界各地。出于同样的原因,我不能假设他们可以让管理员在每次更新时提升他们。 如果可能,我希望避免命令行调用(如通过命令行分配权限,因为这些很可能与操作系统相关) 另一种解决方案是将服务配置为自动并在安装后启动它,但我不喜欢我的服务一直运行的想法,因为它仅在我的主应用程序启动时才需要。 很可能不是文件权限问题。每个人、SYSTEM 和 SERVICE 都可以完全访问 services 文件夹和其中的文件。

这里已经有不同的类似问题,但没有一个给出明确的答案。一位用户可能是使用 WiX-Installer 完成的,但我想保留 Visual Studio 安装程序项目,因为它非常简单易用。

【问题讨论】:

【参考方案1】:

经过一番谷歌搜索并试图找到一个“干净”的解决方案后,我放弃了,现在使用Process.Start 来执行 sc.exe 并在安装后设置新的权限。

这是我的 ServiceInstaller-Class,供任何好奇的人使用:

[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

【讨论】:

在检查了有关此问题的几个主题后,这是唯一一个运行良好的主题!谢谢大佬!

以上是关于以编程方式授予本地用户权限以使用 .Net 启动服务的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式为 Android 服务授予权限

授予特定本地 Windows 用户组对文件夹及其子文件夹的读取权限

Android M:以编程方式撤销权限

Android M:以编程方式撤销权限

以编程方式列出已授予访问权限的 Bigquery 数据集,而无需事先知道项目 ID

如何在android中以编程方式授予系统级权限?