【问题标题】:How can I define this dependency when installing a service安装服务时如何定义此依赖项
【发布时间】:2014-12-04 17:07:49
【问题描述】:

我正在处理一个循环依赖 w.r.t。 Windows 服务及其对驱动程序的依赖。情况如下:

我用 C++ 编写了一个 Windows 服务。该服务依赖于第一次加载/使用驱动程序时安装驱动程序的 DLL;此后,DLL 在运行期间使用驱动程序。

在早期测试中,我将通过命令行调用带有/INSTALL 标志的服务可执行文件来安装服务——这将在内部调用InstallService

然后我遇到了一个问题:服务在我手动启动时会运行,但是当它设置为启动后自动运行时,它会在驱动程序加载之前启动,因此会出错。

为了解决这个问题,我在服务的注册表项@HKLM\System\CurrentControlSet\Services\<SERVICE>DependOnService 值中设置了服务对驱动程序的依赖关系——Windows 将驱动程序与服务类似地对待。这解决了这个问题。

快速部署:我正在使用 WiX 安装和启动服务。在安装过程中,我想将驱动程序设置为我的服务的依赖项。但是,如果我将驱动程序定义为 ServiceInstall 元素中的依赖项,那么 WiX 会在启动我的服务之前尝试启动它,因此我的问题是:WiX 无法在不启动依赖项的情况下启动服务,并且依赖项不存在因为服务还没有运行。

如果我没有在安装程序配置文件中指定依赖项,那么服务会安装并运行良好。

我想我可以在安装服务之后像以前一样在注册表中定义依赖关系,但是那里没有服务的条目!

另一件事:服务现在在启动后运行!没有定义依赖关系!我没有做太多测试来看看这是否一致。

那么,WiX 如何告诉 Windows 存在服务,即为什么没有注册表项?如何指定依赖项?我什至需要再指定一个吗?我是否应该放弃使用与 WiX 服务相关的元素并在安装程序中手动运行我在测试期间执行的命令?

我已经为此苦苦挣扎并研究了至少一个星期;任何见解将不胜感激。


环境信息:

  • 开发:Windows 7,32 位
  • Visual Studio 2010
  • WiX v3.8
  • 部署:Windows 7、32 位和 64 位 -- 自定义、精简图像因此可能不存在标准

【问题讨论】:

  • 我理解你的问题,但是我不明白的是“我用 C++ 编写了一个 Windows 服务。这个服务依赖于一个 DLL,它在第一次加载/使用它时安装驱动程序; 此后 DLL 在运行期间使用驱动程序。" - 听起来像是一个非常糟糕的设计选择,会给你带来很多问题。启动服务不应启动任何安装过程。你为什么那样做?我会说摆脱您的服务所做的任何安装,并开始使用 WiX 的全部功能。
  • WiX 尝试启动您的依赖项听起来也是错误的。它不应该开始任何事情。它只应该安装您的服务所依赖的必要驱动程序/DLL。就是这样。
  • @ChrisEelmaa 抱歉那部分不清楚,也许我可以澄清一下:DLL 中打包了一个.sys 驱动程序文件。第一次使用 DLL 时,如果系统上不存在 .sys 文件,则 DLL 将其解包并将其写入磁盘——它不会启动另一个安装程序或任何东西。以这种方式做事的选择不是我的,而是第三方 DLL 的作者。我想我可以从已经安装它的系统中获取.sys 文件,并让WiX 将它安装到正确的位置;我得调查一下。
  • @ChrisEelmaa 我使用ServiceInstall 元素中的ServiceDependency 元素将.sys 文件指定为服务的依赖项。描述说:Service or group of services that must start before the parent service. 所以我认为 WiX 正在尝试启动依赖项,但是在重新阅读并考虑它之后,一定是 Windows 是在它启动服务之前尝试启动它的那个。
  • 你有没有进一步了解?你说的没有道理。 ServiceInstall 元素将另一个服务作为输入。为什么你会假设你可以在那里传递你的自定义 DLL/sys?你不能。 WiX 处理事情的方式:它将所有内容安装到硬盘上,然后启动您的服务,此时所有依赖问题都已解决。您无需在 ServiceInstall 元素中指定任何内容。

标签: windows-services wix dependencies circular-dependency


【解决方案1】:

我找到了解决办法。

大部分问题是 RTFM 问题(尽管我为自己辩护,文档并不是那么清楚):

我一直在为 ServiceInstall 元素的 Name 属性的值使用通用名称——我的印象是这是用于将 ServiceInstall 元素链接到 ServiceControl 元素的。

ServiceInstall 元素的文档对Name 属性进行了如下说明:

此列是提供要安装的服务名称的字符串。

ServiceControl 元素的文档说:

服务名称。

Name 属性值的实际用途是隐藏的服务的系统名称;这是HKLM\System\CurrentControlSet\Services 下注册表中使用的名称。因此,我的服务被安装在 ServiceManagement 键下,因为那是我在 Name 属性中所拥有的。

不同的名称是导致事情依赖关系工作的原因。显然,除了依赖关系,Windows 按字母顺序加载服务(请参阅this answer 上的 cmets)。当我手动安装时,我的服务的名称在驱动程序的名称之前,因此在未指定依赖项时会出错。我在 WiX 项目的 Name 属性中指定的通用名称位于驱动程序的服务名称之后,因此驱动程序在我的服务之前被加载。

我最终做的是将Name 切换回服务的正确名称,然后将RegistryValue 添加到 WiX 项目以指定我的服务对驱动程序(服务)的依赖。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-16
    • 2022-11-17
    • 2010-11-06
    • 2021-06-05
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多