Wix和延期自定义操作结果

时间:2016-05-02 23:00:35

标签: wix windows-installer driver

简短版

是否可以从用C ++编写的延迟自定义操作设置MSI属性?如果,正如我怀疑的那样,是否有其他方式将延迟自定义操作的结果传达给安装程序,以便我可以做出有条件的ScheduleReboot决定?

TLDR VERSION

我正在为开源文件系统驱动程序(WinFsp)创建一个Wix安装程序。安装程序必须安装驱动程序(FSD)和DLL。经过一些研究后,我确定Windows Installer并不能完全支持这些驱动程序的安装。不过我现在已经创建了一个MSI,可以很好地处理安装/卸载。

然而,有一个问题。由于各种原因,无法停止或卸载此FSD。当用户启动卸载时,MSI能够从SCM中删除FSD服务,然后删除FSD文件。即使FSD服务未停止,这也是可能的。 [这是在Windows上使用此类驱动程序设计的!]

问题是尽管卸载已完成,但FS仍然会加载FSD。在这种情况下,我想执行ScheduleReboot ServiceExists条件,该条件由自定义操作确定:

    <Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" />
    <CustomAction
        Id="Param.ServiceExists"
        Property="A.ServiceExists"
        Value="$(var.MyProductName)" />
    <CustomAction
        Id="A.ServiceExists"
        BinaryKey="CustomActions"
        DllEntry="ServiceExists"
        Execute="deferred"
        Impersonate="no"
        Return="ignore" />
    <InstallExecuteSequence>
        <Custom Action="Param.ServiceExists" Before="A.ServiceExists">REMOVE ~= "ALL"</Custom>
        <Custom Action="A.ServiceExists" After="RemoveFiles">REMOVE ~= "ALL"</Custom>
        <ScheduleReboot After="A.ServiceExists">(REMOVE ~= "ALL") AND SERVICEEXISTS</ScheduleReboot>
    </InstallExecuteSequence>

不幸的是,我发现似乎无法从延迟的自定义操作中执行WcaSetIntProperty。另一方面,对于Wix来说,我是一个完整的n00b,就在几天前我还没有听说过任何关于它的事情。所以请随时向我解释如何做事。

PS:我知道ServiceInstall,但它不支持文件系统驱动程序。此外,Wix Difxapp扩展似乎不是文件系统驱动程序的最佳解决方案(我的驱动程序是旧驱动程序,没有INF文件)。

更新

考虑到这个问题,我想到了两个想法:

  1. 使用RegistrySearch直接检查注册表是否存在FSD,而不是通过服务控制管理器。我不清楚在删除文件后是否可以运行RegistrySearch
  2. 而不是在ServiceExists之后运行RemoveFiles延迟自定义操作,或许我应该运行ServiceRunning立即自定义操作,只检查FSD是否正在运行(卸载时)。这是唯一不会正确删除FSD服务但仅由DeleteService标记为删除的情况。如果有效的话,我会尝试这种方法并将其作为答案发布。

1 个答案:

答案 0 :(得分:1)

正如上次更新中所承诺的,这是我的回答。

我创建了一个ServiceRunning立即自定义操作,在文件系统驱动程序(FSD)上调用QueryServiceStatus。即时自定义操作可以毫无问题地执行WcaSetIntProperty。如果驱动程序正在运行,我将返回的属性用于ScheduleReboot(因为FSD无法停止/卸载,因此在卸载后将保持“挂起删除”)。

以下是相关的Wix代码:

    <Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" />
    <CustomAction
        Id="Params.ServiceRunning"
        Property="ServiceRunning"
        Value="$(var.MyProductName)" />
    <CustomAction
        Id="Action.ServiceRunning"
        BinaryKey="CustomActions"
        DllEntry="ServiceRunning"
        Execute="immediate"
        Return="ignore" />
    <InstallExecuteSequence>
        <Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning">REMOVE ~= "ALL"</Custom>
        <Custom Action="Action.ServiceRunning" After="RemoveFiles">REMOVE ~= "ALL"</Custom>
        <ScheduleReboot After="Action.ServiceRunning">
            <![CDATA[(REMOVE ~= "ALL") AND (0 <> ServiceRunning)]]>
        </ScheduleReboot>
    </InstallExecuteSequence>