【问题标题】:Wix stop service on uninstall/upgrade: prevent "restart popup" (file-in-use situation)Wix 在卸载/升级时停止服务:防止“重新启动弹出窗口”(文件使用中的情况)
【发布时间】:2015-08-03 12:51:40
【问题描述】:

我遇到了一个问题,即在卸载(或升级)时,重启管理器抱怨文件正在使用中,因此强制重启:

RESTART MANAGER: Detected that application with id 7000, friendly name 'javaw.exe', of type RmCritical and status 1 holds file[s] in use.
RESTART MANAGER: Did detect that a critical application holds file[s] in use, so a reboot will be necessary.

RESTART MANAGER 抱怨的服务是基于 java 的服务。该服务(此处称为 myservice.exe)正在递归启动 java 子进程:

  myservice.exe --run
↳ javaw.exe --someArguments
↳ someother.exe --someArguments
↳ javaw.exe --someMoreArguments

服务定义的 wix sn-p:

<DirectoryRef Id="BINDIR">
        <Component Id="myservice.exe" Guid="PUT-GUID-HERE">
            <File Id="myservice.exe" KeyPath="yes" Vital="yes"
                  Source="SourceDir\bin\myservice.exe"/>
            <ServiceInstall Id="MyService" Type="ownProcess"
                            Vital="yes" Name="MyService" DisplayName="My Service"
                            Description="My Service" Start="auto" Account=".\LocalSystem"
                            ErrorControl="normal" Interactive="no" Arguments="--run"/>
            <ServiceControl Id="MyService" Name="MyService" Wait="yes" Remove="uninstall" Stop="uninstall" Start="install"/>
        </Component>
</DirectoryRef>

现在,有趣的部分:

  • 安装时可以启动服务

卸载时:

  • 如果不运行,将被删除
  • 如果正在运行,并且只是同意重新启动
    • 它确实在大约 2-3 秒内停止(我猜是通过 StopServices 操作)
    • 并成功移除(通过 RemoveServices 操作)

到目前为止,Service* Tables 中的条目对我来说似乎不错。

ServiceControl-Table:
ServiceControl  Name       Event  Arguments  Wait  Component_
MyService       MyService  161               1     myservice.exe

ServiceInstall-Table:
ServiceInstall  Name       DisplayName  ServiceType StartType ErrorControl LoadOrderGroup Dependencies StartName Password Arguments Component_     Description
MyService       MyService  My Service   16          2         32769        .\LocalSystem                                  --run     myservice.exe  My Service


所以,分解所有内容: 似乎重新启动管理器没有识别出 java 进程是子进程并且将被 StopServices 操作停止。

我在这里发现了一些类似的问题: https://www.mail-archive.com/wix-users@lists.sourceforge.net/msg57924.html
Wix Installer Problem: Why does RestartManager mark Service as RMCritical and not RMService

提前感谢您为解决此问题提供的任何帮助!

【问题讨论】:

    标签: wix windows-installer restartmanager


    【解决方案1】:

    您有几个选项可以解决此问题:

    -通过使用属性表中的 MSIRESTARTMANAGERCONTROL=“禁用”禁用“重新启动管理器”。这将启动旧的“FilesInUse”对话框。 在您的情况下,也可能不会显示 FilesinUse 对话框(因为服务没有与之关联的窗口) “FilesinUse”对话框不会列出没有与之关联的窗口的进程。因此,在您的情况下,禁用重新启动管理器可能不会显示任何对话框(FilesInUse 和 RestartManager 都不显示)。

    但是,这也意味着可能需要重新启动,这不一定是因为您的服务,而是由于某些其他进程可能正在使用您的文件。如果您认为除了您自己的服务保存文件之外没有其他进程,那么请继续遵循此方法。如果您认为除了保存文件的服务之外可能还有其他进程,那么启用“重启管理器”是理想的选择。没有“重启管理器”会导致以下情况之一:

    -显示 Legacy FilesInUse 对话框,要求您关闭对话框中列出的进程。这可能会导致您必须通过自定义操作关闭这些进程。

    “RestartManager”和“FilesInUse”对话框均由“InstallValidate”标准操作显示。如果您想禁止这两个对话框,请确保在“InstallValidate”标准操作之前安排您的自定义操作。这里有一个问题。在 InstallValidate 之前安排这样的自定义操作必须是立即模式自定义操作(您不能在“IntsallFinalize”之前有延迟模式自定义操作)。因此,如果您不是以管理员身份运行(例如在启用 UAC 的情况下),您可能没有必要的权限来关闭应用程序。因此,可能需要重新启动。

    -您还可以使用 WiX 实用程序扩展 CloseApplication() 函数关闭应用程序。 评估您的方案并做适合您的事情。

    【讨论】:

    • 设置 MSIRESTARTMANAGERCONTROL="Disable" 做得非常好。无论如何,我现在遇到了另一个问题:InstallValidate 操作现在在日志中声明,msvcr100.dll 由其他一些进程持有。问题是,这些进程确实有一个 msvcr100.dll 的句柄,但不是这个安装提供的句柄。他们有自己的(使用 ProcessExplorer 检查)。结果,显示“FileInUse”-Dialog,需要关闭 Outlook 才能继续(在我的情况下,是唯一具有窗口的应用程序)。安装程序是否有可能在这里以某种方式存在错误?
    • 您的安装中不太可能存在错误。相信 FilesInUse 和 RestartManager 所做的事情。我已经看到即使打开命令窗口也会抱怨要求我关闭命令窗口的安装。我不认为有任何错误,这只是这些事情的工作方式。只是一个疯狂的猜测。如果您的进程使用的 msvcr100.dll 是从 C:\windows\winsxs ... 目录使用的,那么即使是 Outlook.exe 也可能使用相同的目录。 FileInUse 发现 Outlook.exe 有一个与之关联的窗口,因此将其标记为关闭。
    • 你在哪里安装你的运行时 dll 的?在全局 winsxs 目录或应用程序文件夹中。
    • 进入应用程序文件夹。日志文件显示:InstallFiles:文件:msvcr100.dll,目录:D:\myapplication\jre\bin\,大小:773968 1:{C5A8FA5F-A1FF-4506-8673-855F34E94824} 2:{E769B299-36EE-58F1- 961F-2EC7CA556566} 3: D:\myapplication\jre\bin\msvcr100.dll
    • 发布了一个新问题,因为这似乎是一个不同的问题:stackoverflow.com/questions/31809323/…
    【解决方案2】:

    我想我参加聚会可能会迟到,但这是解决方案。 Installer team blog post 解释了重启管理器如何决定是否弹出正在使用的文件对话框。具体来说(Windows Installer-Restart Manager Interaction in Detail 部分,第 3.b 项):

    如果包的编写这样 RM 检测到的服务将因编写 Service* 表而关闭,那么这些服务将不会显示在使用中的文件对话框中。

    (斜体是我的)。有帮助但不会立即有帮助,因为这样并没有真正详细说明。但是由于我的服务引起了与 OP 描述的相同的问题

    <ServiceControl Stop="uninstall" ... />
    

    我只是将值更改为both

    <ServiceControl Stop="both" ... />
    

    这可能是唯一可以让它“这样”的东西了,轰隆隆,烟花,魔法

    MSI (s) (50:A0) [21:50:30:352]: RESTART MANAGER: Detected that application with id 6408, friendly name 'XXXX', service short name 'xxxx', of type RmService and status 1 holds file[s] in use.
    MSI (s) (50:A0) [21:50:30:352]: RESTART MANAGER: Detected that the service xxxx will be stopped due to a service control action authored in the package before the files are updated. So, we will not attempt to stop this service using Restart Manager
    

    似乎需要在ServiceControl table 中设置 both 标志 msidbServiceControlEventStop (0x002) 和 msidbServiceControlEventUninstallStop (0x020) 以使RM 高兴地得出结论,该服务将在文件更新之前停止。


    回想起来,这是有道理的。由于升级过程中的卸载部分是使用 旧缓存 MSI 数据库执行的,因此 RM 不会查看它以查看卸载相关产品时会发生什么。严格来说,可能有多个产品需要卸载,安装程序并不要求这些相关产品FindRelatedProducts action找到的,包括旧版本的相同升级代码)在任何地方事实上与在 current 包中控制的服务有关。因此,它不关心 current 包中脚本的卸载服务操作(它无论如何都不适用于安装操作!)。为了保持一致性,它需要一个简单而直接的证据,证明服务将在正在使用的文件被覆盖之前停止,仅从当前包中收集此类证据。

    因此,RM 很可能只在安装期间关心 msidbServiceControlEventStop (0x002) 标志。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      • 2018-10-28
      • 2011-06-03
      • 1970-01-01
      • 2013-04-30
      相关资源
      最近更新 更多