【问题标题】:Can I delegate windows service execution to another process?我可以将 Windows 服务执行委托给另一个进程吗?
【发布时间】:2012-01-03 17:31:11
【问题描述】:

我希望能够启动 Windows 服务,启动另一个可执行文件,然后退出,让启动的可执行文件作为服务代替自身运行。

进程将能够相互通信,因此任何一个进程所需的来自另一个进程的任何信息都是可用的。

这可以在 .NET 中实现吗?

编辑:为了澄清,这是工作流程的样子:

  1. 服务启动,启动 a.exe。注意:a.exe 调用 ServiceBase.Run()
  2. a.exe 使用 Process.Start() 启动 b.exe
  3. a.exe 和 b.exe 完成交换信息所需的任何通信,例如进程或服务句柄(注意:此功能已经存在)
  4. a.exe 将服务控制权分配给 b.exe
  5. a.exe 退出,b.exe 继续运行并绑定到服务控件

【问题讨论】:

  • 如果服务进程退出“进程将能够相互通信”是不可能的。
  • 呃,如果服务退出,他们将如何通信?管理员应该如何停止和重新启动服务?它真的不再是一项服务,而是一个没有人能够控制的过程。
  • 第 4 步和第 5 步当然是难点,你不能做到这一点。服务控制器只知道它启动的服务。服务控制回调是特定于进程的。使用ServiceController类来控制b.exe,它也需要是一个服务。
  • @DanielShaffer 如果您能够设法将 b.exe 的进程 ID 传递回服务,您应该能够控制它。您可以考虑扩展您用于在 a.exe 和 b.exe 之间进行通信的任何通信机制,以允许 b.exe 与服务通信。一种方法是在它们之间打开一个套接字连接。

标签: c# windows-services


【解决方案1】:

不,您不能更改绑定到服务控制管理器的进程。要了解为什么这是不可能的,您需要了解非托管 Windows 服务 API 的工作原理。 (.NET 正在包装)。

您通过调用StartServiceCtrlDispatcher(只能调用一次)连接到服务控制管理器。在lpServiceTable 参数中传递一个指向ServiceMain 函数的指针,这显然只对当前进程有效,并且所有的服务控制通知都发送到该函数。

在所有服务停止之前,对StartServiceCtrlDispatcher 的调用也不会返回。因此,管理的服务控制也与启动服务的进程中的线程相关联,因此如果不切断与服务管理器的链接,则无法退出。

因此,在您的示例中,第 4 步不能发生,并且进程 a.exe 需要在此期间保持活动状态。

【讨论】:

  • 如果我使用已启动进程的句柄而不是当前进程的句柄创建了一个 SERVICE_TABLE_ENTRY 怎么办?我意识到我基本上会重新实现 ServiceBase.Run(),但似乎可以做到?
  • 不,SERVICE_ENTRY_TABLE 不包含进程句柄 - 它始终使用当前进程。
【解决方案2】:

请参阅Process.Start()this tutorial(旧的,但仍然可以使用)、or this one

如果您尝试启动已注册的服务,this may help

一旦新进程运行,与它的通信与任何其他进程间通信secnario 具有相同的要求。

您可以使用 WCF、打开套接字、使用数据库等。如果没有更多关于您需要哪种通信的详细信息,很难推荐一种特定的方法。

【讨论】:

  • 我已经使用 Process.Start 来启动第二个进程。 IPC 已经得到照顾 - 我只在问题中提到它是为了表明它在需要时可用。我主要感兴趣的是让服务控制绑定到第二个进程而不是第一个进程。
猜你喜欢
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 2010-12-13
  • 2015-01-10
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
相关资源
最近更新 更多