2011-08-23 134 views
1

我对正在开发的应用程序有点麻烦。 这里是场景:我有两个用C#编写的Windows服务(服务A和服务B)。如何通过另一个Windows服务创建Windows服务

服务A负责在两个应用程序(使用Web服务,FTP连接等)之间传输数据。它也负责更新服务B.

服务B负责更新服务A和更新Web应用程序。

更新的基本操作(可以说这是更新服务A的过程中,服务B完成):

  1. 通过Web服务检查更新
  2. 如果有新版本,停止该服务(使用C#ServiceController)。该服务的
  3. 备份当前的文件
  4. 卸载服务(使用SC delete命令)
  5. 下载服务的更新的文件(这样我就可以做一个回滚,如果出现错误)(使用FTP连接)
  6. 执行一些SQL Server脚本(如果存在)
  7. 安装Windows服务(使用SC创建命令)
  8. 启动服务(使用C#的ServiceController)

一切顺利,直到第7步。我认为问题是用户正在执行更新(运行服务B的用户)没有创建新的Windows服务的权限,所以SC创建总是返回类似于“[SC] OpenSCManager失败5:访问被拒绝“ 请注意,我有两个服务与本地系统帐户一起运行。所以,我认为这个帐户不能创建新的Windows服务(如果我错误地认为我是正确的)。

之后,我创建了一个新的Windows用户,只是为了运行这些服务。这个想法是给这个用户必要的权限(网络共享,文件和创建服务)。但是,该用户仍然无法创建该服务。

这是我已经试过:

  1. 给用户的cmd.exe和SC.EXE权限(使用CACLS)。
  2. 使用PsExec直接运行cmd(使用-i -s)而不是cmd.exe。
  3. 使用SubInAcl命令,以便用户有权使用这两个Windows服务。但是这是事情,当时我没有任何服务,所以它不起作用。

一些remarkes:

  • 此Windows服务没有任何安装程序。
  • SC命令使用C#ProcessStartInfo运行。
  • SC命令指定我创建的Windows用户的用户名和密码。
  • 我真的不希望Windows服务在具有管理特权的用户帐户下运行。

我知道这个线程类似于一些已经在这里Auto-update a Windows Service,但是我找不到任何工作的解决方案。

很抱歉的长文本

回答

2

我觉得你的基本设计是易碎和有缺陷的。作为正常服务操作的一部分,您不应该删除和创建服务。

我会做的是安排任何需要更新的服务都能够自行完成。基本上把所有需要更新的代码放在一个DLL中。服务EXE中的代码只是一个瘦主机,负责加载主DLL并调用它的主要处理循环。当EXE确定是时候更新它时,下载新的DLL,据推测可以通过散列检查它是否正确下载。接下来处理循环终止,旧的DLL被卸载,新的DLL被加载并且处理循环再次开始。

这种方法侵扰性小得多,避免了所有的权限和权限问题。您可以编写单个服务主机EXE并拥有包含逻辑的多个DLL。

+0

+1,它有助于测试/调试,因为您可以为DLL(s)创建测试套件... – Yahia

+0

感谢您的回答。我会尝试这种方法。 –

+0

在这里你需要非常小心线程。特别是,您的处理程序回调函数将需要位于服务EXE中,并且需要正确处理DLL被替换时进入的请求。 (当然,你必须确保你不会卸载DLL,而处理器回调函数仍然在使用它。) –

相关问题