3

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

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

提前感谢您的任何指点。

4

11 回答 11

2

Win32 服务被设计为系统范围的,并在任何用户登录之前开始运行。如果您希望在每个用户的基础上运行某些东西,最好将其设计为常规应用程序并从用户的 Startup 运行它团体。

于 2008-09-22T05:22:06.880 回答
0

服务的整个概念是它在任何用户登录之前启动。因此,即使这是可能的,您也无法在服务启动时在 userA 和 userB 之间进行选择,因为它们都还没有登录。


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

于 2008-09-22T05:23:19.403 回答
0

是否有可能让服务创建子进程,然后采用用户凭据(或从它们开始)?这样,您仍然仅限于服务的单个实例,但它能够以同样的方式完成每个用户的工作。IIRC Windows 任务计划程序服务执行此操作。

于 2008-09-22T05:28:30.420 回答
0

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

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

那可能吗?

于 2008-09-22T05:29:25.770 回答
0

您可能正在寻找模拟用户。在此处查看我通过快速 Google 搜索找到的一些参考资料:

于 2008-09-22T05:41:05.257 回答
0

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

  1. 以每个登录用户身份运行
  2. 即使没有用户登录也会自动运行。

没有办法简单地做到这一点,而是考虑将您的程序包装在服务中;该程序将在每个用户的启动时正常运行(通过启动文件夹或任务调度程序),此外还创建一个服务以作为系统用户(或您定义的任何其他用户)运行您的应用程序。
由于您还需要(您在评论中提到这一点)应用程序即使在他注销后仍以最终用户身份继续运行,您可以让服务为您管理此过程。

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

于 2008-09-22T06:05:16.277 回答
0

您可以创建一个服务应用程序和一个非服务(普通)应用程序,并让它们通过 IPC(映射文件、管道、MailSolts ......你的名字)进行通信。

这样你就解决了所有的麻烦。

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

于 2008-09-22T06:19:08.147 回答
0

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

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

于 2008-09-22T15:07:57.173 回答
0

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

如果您使特权服务的代码尽可能简单,则此模式还有一个额外的好处,就是您可以最大限度地减少代码的攻击面。如果用户在您的服务的“以用户身份运行”端发现安全问题,这不是问题,而特权服务中的安全问题可能会导致权限提升。事实上,在实现 Windows 消息处理循环的 Vista 特权服务之前,很容易受到一种称为Shatter 攻击的攻击,鉴于您正在尝试执行的操作,您应该意识到这一点。

于 2008-09-22T15:20:21.467 回答
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,则可以使用其他通信渠道将凭据传递给您的服务。

无论如何,一旦您的服务获得凭据,代表用户的所有工作都必须在后台线程上执行,以免阻塞以用户身份运行的应用程序。

于 2008-09-26T05:29:08.357 回答
0

你希望它一直运行,所以你需要一个服务。

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

于 2008-11-07T17:59:55.410 回答