来自同一可执行文件的多个服务

时间:2008-09-22 05:20:02

标签: c++ winapi service

我写了一个小服务(普通Win32),我想知道当多个用户登录时是否可以运行多个实例。

基本上,假设我们为UserA提供了UserA和UserB,该服务将以“domain \ UserA”身份登录,而对于UserB,该服务将以“domain \ UserB”身份登录 - 这是来自相同的可执行文件。我可以使用ChangeServiceConfig()函数动态更改登录,但它似乎在系统范围内更改它,而我希望每个用户都有自己的服务副本只为他运行。

提前感谢您的任何指示。

11 个答案:

答案 0 :(得分:2)

Win32服务设计为系统范围,并在任何用户登录之前开始运行。如果您希望按用户运行某些内容,最好将其设计为常规应用程序并从中运行用户的启动组。

答案 1 :(得分:0)

服务的整个概念是在任何用户登录之前启动它。所以即使这是可能的,当服务启动时你也无法在userA和userB之间做出选择,因为它们都没有登录。


可能的方向是服务以SYSTEM身份运行并且每隔几分钟检查是否有用户登录,如果有冒充该用户并执行此操作。

答案 2 :(得分:0)

是否有可能让服务创建子进程然后采用用户凭证(或者用它们启动)?这样,您仍然只能使用该服务的单个实例,但它能够完全执行每个用户的工作。 IIRC Windows任务计划程序服务执行此操作。

答案 3 :(得分:0)

是的,这听起来很接近(我正在回答Greg的评论,但评论太短,不适合我的回复)。

我事先并不知道用户列表,但是有一个GUI控件应用程序可用于为每个用户输入用户名/密码对。因此,userA将登录,运行应用程序,输入他的凭据,服务将使用它。同时(在userA已注销但服务仍在使用userA的凭据运行之后)userB登录,使用该应用程序,另一个服务副本开始按用户B登录运行。因此,同时userA和userB服务正在运行。

这可能吗?

答案 4 :(得分:0)

您可能希望模拟用户。在这里查看我通过快速Google搜索找到的一些参考文献:

答案 5 :(得分:0)

听起来好像你实际上有两个不同的,相互冲突的要求,关于时间和身份。

  1. 以每个登录用户身份运行
  2. 即使没有用户登录也会自动运行。
  3. 无法做到这一点,而是考虑将您的程序包装在服务中;程序将在启动时为每个用户正常运行(通过启动文件夹或taskscheduler),此外创建一个服务,以系统用户(或您定义的任何其他用户)的身份运行您的应用程序。
    由于你还需要(你在评论中提到这个)应用程序即使在他注销后仍然作为最终用户运行,你可以让服务为你管理这个过程。

    然而,这可能不是最好的主意,因为用户仍然有效登录。这可能有许多副作用,包括安全性,性能(一次登录的用户太多......)等。

答案 6 :(得分:0)

您可以创建服务应用程序和非服务(普通)应用程序,并通过IPC(映射文件,管道,MailSolts ......您为其命名)进行通信。

这样你就可以解决所有麻烦。

注意:相同的应用程序可能有不同的行为 - 当作为进程启动时和用户启动时,但最终它是相同的,您仍然有2个应用程序(无论您是否只有一个可执行文件)。

答案 7 :(得分:0)

可以使用不同的帐户运行。实际上,这很常见。请参阅svchost.exe,它实现了一堆OS服务。

我只是不知道你如何确定哪些帐户。在一家大公司中,设置了许多PC,因此所有100,000多名员工都可以使用它。您不希望以登录用户身份运行服务,也不想为所有100.000用户运行它。那么对于哪些帐户,我要问?

答案 8 :(得分:0)

Windows进程一次只能使用一个用户的权限执行。这适用于服务和其他流程。有足够的权限,可以通过模拟在不同用户之间“切换”。您尝试执行的操作的最常见模式是拥有一个特权服务实例,该实例注册以登录/注销事件并相应地创建子进程,每个进程都模拟登录用户。该模式还将简化UI,因为每个进程都在每个单独用户的桌面上运行,就像它是常规应用程序一样。

如果您使特权服务的代码尽可能简单,则此模式具有额外的好处,即您可以最小化代码的攻击面。如果用户在您的服务的“作为用户运行”方面发现安全问题,则这不是问题,而特权服务中的安全问题可能导致权限升级。实际上,在实现Windows消息处理循环的Vista特权服务之前,很容易受到一种名为Shatter attacks的攻击,你应该知道你要做的事情。

答案 9 :(得分:0)

您不需要多个服务实例。从您对问题的描述来看,您需要的是一种可以模仿用户并代表他们执行作业的服务。

您可以通过实现服务中托管的COM对象来完成此操作。您的客户端应用程序(最终用户运行)将在您的CLSID上调用CoCreateInstanceEx。这将导致在您的服务中创建COM对象的新实例。然后,应用程序可以使用您的某个接口上的方法将收集的用户凭据传递给COM对象(尽管我对收集凭据持谨慎态度,而不是查看是否可以传递用户令牌)。然后,在服务上下文中运行的COM对象可以调用LogonUser()来登录用户并模拟它,因此它可以代表她做任何事情(比如查找用户本地appdata文件夹:-))。其他答案提供了使用凭据或令牌模仿用户的良好链接。

如果您对COM感到满意,我建议您将对象创建为多线程(生活在MTA中),以便COM不会序列化它们的执行。如果没有,默认的单线程模型就足够了。

Visual Studio ATL向导可以生成服务中的COM对象的骨架。您还可以在此处阅读有关使用ATL实现Windows服务的信息:http://msdn.microsoft.com/en-us/library/74y2334x(VS.80).aspx

如果您根本不了解COM,可以使用其他通信渠道将凭据传递给您的服务。

在任何情况下,一旦您的服务获得凭据,代表用户的所有工作都必须在后台线程上执行,以便不阻止以用户身份运行的应用程序。

答案 10 :(得分:0)

您希望它一直在运行,因此您需要一项服务。

您需要跟踪每个用户的内容,因此您需要一个在用户会话中运行并与服务通信的应用程序(使用命名管道或DCOM或符合您要求的任何内容)。