是否可以从用C ++编写的延迟自定义操作设置MSI属性?如果,正如我怀疑的那样,是否有其他方式将延迟自定义操作的结果传达给安装程序,以便我可以做出有条件的ScheduleReboot
决定?
我正在为开源文件系统驱动程序(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文件)。
考虑到这个问题,我想到了两个想法:
RegistrySearch
直接检查注册表是否存在FSD,而不是通过服务控制管理器。我不清楚在删除文件后是否可以运行RegistrySearch
。ServiceExists
之后运行RemoveFiles
延迟自定义操作,或许我应该运行ServiceRunning
立即自定义操作,只检查FSD是否正在运行(卸载时)。这是唯一不会正确删除FSD服务但仅由DeleteService
标记为删除的情况。如果有效的话,我会尝试这种方法并将其作为答案发布。答案 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>