一个 exe 中的多个 Windows 服务

Posted

技术标签:

【中文标题】一个 exe 中的多个 Windows 服务【英文标题】:Multiple Windows Services in One exe 【发布时间】:2010-10-23 10:03:57 【问题描述】:

我正在尝试构建几个 Windows 服务来做不同的事情。例如,我需要以下 Windows 服务:

    通过电子邮件发送每日报告 每隔 30 分钟定期清理一些存档信息 等

我需要 Windows 服务来完成的任务是不同的,所以我不太喜欢将它们全部放在一个服务中的想法。

到目前为止,我得到的是 Visual Studio 2008 中的一个项目。我创建了一个 Windows 服务,我在 OnStart 事件上设置了一个计时器(它只是每 5 秒写入一个文本文件以进行测试目的)。然后我在项目中添加了一个安装程序,当我运行 InstallUtil.exe 时,一切正常。

当我向同一个项目添加第二个 Windows 服务时,问题就出现了。我再次设置了 OnStart 代码,使用相同的日志记录信息(略有不同,因此我可以知道哪个服务正在写入日志)。使用第二个 Windows 服务,我将 Program.cs 中的 Main 事件从:

    static void Main(string[] args)
    
        ServiceBase[] ServicesToRun = new ServiceBase[] 
         
            new Service1()
        ;

        ServiceBase.Run(ServicesToRun);
    

到:

    static void Main(string[] args)
    
        ServiceBase[] ServicesToRun = new ServiceBase[] 
         
            new Service1(),
            new Service2()
        ;

        ServiceBase.Run(ServicesToRun);
    

此时,没有编译时错误,但 Service2 服务从不做任何事情......日志记录任务永远不会触发。

我将其缩小到第二个服务没有与之关联的“安装程序”这一事实。然后我尝试像使用第一个服务一样添加安装程序(即,右键单击服务设计器,然后单击“添加安装程序”)。现在,当我转到 ProjectInstaller.cs 文件时,那里还有另一个 serviceInstaller (serviceInstaller2)。

现在,当我构建项目并尝试安装服务时,我转到“服务”控制面板窗口,尝试启动 Service1,我收到以下错误消息:

Windows 无法在本地计算机上启动 Service1 服务。

错误 1083:配置此服务运行的可执行程序未实现该服务。

如果我也尝试启动 Service2,我也会收到相同的错误消息(当然,错误消息标识 Service2 除外)。

为了让两个服务从一个 exe 运行,我有什么遗漏吗?

【问题讨论】:

除了“我想”之外,还有什么特殊原因需要您将服务放在一个可执行文件中吗?通常,模块化会更可取,但您可能会遇到需要其他情况的情有可原的情况。 唯一真正的原因是易于安装和部署。所有的“服务”都是相当快的一项功能,所以我不希望为一小段代码安装 x 个 Windows 服务。 @pyrochild -- 我相信在一个程序集中安装多个服务的原因有很多。我现在工作的地方,我们在每个客户的基础上使用这种设计的野兽——它使与这些服务交互的测试软件变得轻而易举。 This might help 【参考方案1】:

我已经想出了如何拥有一个可执行文件和两个服务。每个服务都以自己的名称和启动/停止能力安装到服务管理器。我想这就是你想要的,对吗?这是我所做的:

    创建了一个服务项目。 向同一项目添加了第二个服务(具有唯一的服务名称)。 为两个服务(ServiceA 和 ServiceB)添加了安装程序。 在 ProjectInstaller.Designer.vb 文件中,我更改了 Me.Installers.AddRange 行以显示两个服务安装程序。 (Me.ServiceInstaller1, Me.ServiceInstaller2) 在主服务(在我的例子中是 ServiceA)的 Main 入口点中,我将 ServicesToRun 变量设置为包含我希望它运行的所有服务(ServiceA 和 ServiceB)的 ServiceBase 数组。这是一个重要步骤,因为服务管理器根据此处的参数数量设置属性 - 允许同一 exe 的多个实例或仅允许单个实例。 添加安装程序项目并使用服务的输出。 使用服务的输出添加自定义操作。

您可以在此处找到演示代码:http://code.google.com/p/multi-service-install/

享受吧!

【讨论】:

嗨,谢谢你的评论,但我不明白第 4 点,你能更新你的代码吗【参考方案2】:

我想你们已经解决了这个问题,但如果其他人需要它,我会发布一个答案,这个问题今天花了我几个小时。 解决的办法不是添加另一个项目安装程序,而是添加一个服务安装程序,它是项目安装程序上的一个组件。新添加的服务安装程序必须配置第二个服务名称。

【讨论】:

我不得不使用这里的细节来告诉我如何做到这一点:msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx 对于懒惰的人:“打开设计器窗口的上下文菜单(如果您使用的是指点设备,对- 在窗口内单击),然后选择添加安装程序。” @RitwikSen,我认为他指的是当时或写作(2009 年)可用的项目类型,它为最终用户生成程序安装向导。这从 VS2012 开始被删除,但仍可作为 VS 市场的扩展。但我建议为此使用其他东西,因为它会产生非常陈旧的 UI,并且在 64 位应用程序中存在错误。【参考方案3】:

我今天遇到了类似的问题,并设法解决了。

首先,我确保每个服务都有一个有意义且唯一的 ServiceName 属性。生成器为这两个服务都赋予了相同的名称,这不会有帮助。

然后我删除并重新生成了 ProjectInstaller 类,并为每个类添加了安装程序。我确保它们都在静态 Main 方法中实例化。

我现在可以使用一个 dll 安装这两个服务,但不幸的是,当我启动其中一个服务时,它似乎同时执行自身和另一个服务的功能。也就是说,这两项服务都在运行(即使只有一项服务在计算机管理器中显示为“已启动”)。我还在努力解决这个问题...

【讨论】:

【参考方案4】:

我实际上正在构建与您的想法非常相似的东西。我决定做的(到目前为止)是让我所有的“服务”(虽然它们不是服务,但一个“控制器”是)实现一个特定的接口(也使用 init() 和 execute() 操作作为 FREQUENCY 枚举)。

控制器是 Windows 服务,它在运行时从 xml 设置文件中读取程序/dll 列表,并将它们加载到列表中,并以它们定义的任何频率调用它们的 execute() 方法(如果适用)。

在我的例子中,每个程序还包含一个用户控件,它被加载到控制器的标签页中,允许用户控制/修改它。如果你有兴趣,我会发布代码。

不确定这是否清楚。我实际上是从另一个 SO 用户那里得到这个想法的,他实现了类似的东西,但我现在找不到那个帖子。

【讨论】:

【参考方案5】:

我使用 sc.exe 轻松完成此任务。 http://support.microsoft.com/kb/251192

例如:sc create "My Display Service Name" binpath= "c:\app\mysvc.exe --service"

注意:每个等号都应该在其值之前有 空格,正如您在 'binpath' 中看到的那样

【讨论】:

如果有人像我一样来到这里并希望使用 sc.exe 使其工作(因此,无需安装程序):binpath 末尾的 --service 是您可以添加的参数到您的服务主要方法。在那里,您可以根据此类参数切换要启动的服务。 More info here【参考方案6】:

在一个可执行文件中安装 2 个不同且不相关的服务对我来说有一种奇怪的味道。虽然有可能让它工作,但它并没有使它正确。

听起来,您需要在不同的时间间隔执行一些不同的任务,并且您的任务可能相关也可能不相关。你看过 Quartz.NET 吗?这听起来很适合您的需求。

http://quartznet.sourceforge.net/features.html

【讨论】:

【参考方案7】:

我今天遇到了同样的问题并设法解决了它。 在我的情况下,我只需要打开我的服务的 *.designer.cs 文件并确保服务名称设置正确。更重要的是,如果您在 *Installer.cs 中有代码,则应在 *Installer.Designer.cs 中使用相同的名称。

我认为这个错误只是因为名称不匹配。

希望对你有帮助

【讨论】:

以上是关于一个 exe 中的多个 Windows 服务的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个启动和停止多个'exe'/'bat的Windows服务

jq-win64.exe:从 Windows 批处理文件中的 JSON 文件解析数据

windows打开程序过程

win7怎样删除windows installer服务

windows 服务主进程是啥?

使用nssm将命令行启动的应用程序(.exe,.bat等)注册成windows后台服务