Installation 如何在基于MSI的卸载过程中停止正在运行的进程?

Installation 如何在基于MSI的卸载过程中停止正在运行的进程?,installation,windows-installer,wise,altiris,Installation,Windows Installer,Wise,Altiris,我正在Windows XP上使用Wise Package Studio 7.0 SP2 我有一个MSI包装的EXE安装程序,它可以愉快地安装一些文件,然后运行安装程序中的一个文件,我们可以称之为app.EXE 因此,在MSI编辑器的“执行延迟”选项卡上,我必须添加以下行: If Not Installed then Execute Installed Program app.exe (Action) End 这确保了my app.exe仅在安装时运行,而不是在修改/修复/删除期间运行。当a

我正在Windows XP上使用Wise Package Studio 7.0 SP2

我有一个MSI包装的EXE安装程序,它可以愉快地安装一些文件,然后运行安装程序中的一个文件,我们可以称之为app.EXE

因此,在MSI编辑器的“执行延迟”选项卡上,我必须添加以下行:

If Not Installed then
  Execute Installed Program app.exe (Action)
End
这确保了my app.exe仅在安装时运行,而不是在修改/修复/删除期间运行。当app.exe运行时,它会方便地将自己添加到系统托盘中

我正在寻找一种可以在移除过程中起相反作用的东西。我想停止app.exe进程,从而将其从系统托盘中删除

目前,我的删除将删除所有文件,但是app.exe仍在运行,并且仍显示在系统托盘中。我已经考虑过添加条件语句:

If REMOVE~="ALL" then
  *remove the app from the systray!*
End

条件语句只允许我在删除时执行某些操作,但是我不确定实际终止进程的最佳方法。是否有一个MSI命令我可以运行,让我这样做?我是否应该编写自己的.exe来执行此操作?

您可以将VBscript元素作为自定义操作插入MSI。像这样的东西应该可以完成这项工作:

strMachine = "localhost"
strAppName = "notepad.exe"

Set objProcesses = GetObject("winmgmts://" & strMachine).ExecQuery("SELECT * FROM Win32_Process WHERE Caption LIKE '" & strAppName & "'")

For Each objProcess In objProcesses
    intRetVal = objProcess.Terminate(0)
Next

6个月前,我们使用VBScript操作来做同样的事情,然后就在SP3发布的时候,objProcess.Terminate()函数只是拒绝在某些机器上工作。不管我们怎么做,它都僵住了。这种情况发生在我们大约10%的测试机器上,因此我们不得不寻找替代解决方案(谁知道它可能冻结了多少客户!)

我的第一个发现是内置(自Windows 2000以来)命令TASKKILL 例如:
TASKKILL/IM app.exe/F
但由于它似乎使用了与我们在VBScript中使用的类似的终止进程的方法,因此该方法也会失败

因此,现在我们正在使用sysinternals中的
pskill.exe
工具,您需要使用命令行开关来抑制许可协议提示符,但除此之外,这是我发现的杀死正在运行的exe的最简单的方法


当然,最好的解决方案是建立自己的EXE或DLL来做它,如果你碰巧知道一点C++,那么)p> 仅仅终止进程是不够的,因为这不会清理Windows通知区域(但是,当鼠标下一次悬停在中时,Windows将清理没有匹配进程的图标)。然而,突然终止应用程序的另一个原因通常最好是留给调试。不幸的是,更恰当的解决方案也更为复杂。您可以在应用程序中创建一个命名事件,并注册一个回调方法,以便在设置时调用。回调将关闭应用程序。然后您将编写一个自定义操作来设置事件并等待进程终止


如果您需要支持取消(例如,提示用户有未保存的更改并决定不取消),您可以使用另一个命名事件来表示,因此自定义操作可能会等待进程结束或取消事件,以先到者为准。

如果您的app.exe是在内部创建的,您可以添加一个命令行,告诉它终止当前正在运行的命令行。当给出该命令行时,它会向程序的第一个实例发送一条消息或其他信息,告诉它退出,然后等待程序的第一个实例实际终止。然后,安装程序将能够使用kill开关运行程序,并知道当kill开关实例返回时,程序的原始实例已不存在。

这不是一个可靠的解决方案,根据我的经验,根据sascha所述,在大量运行XP SP3的机器上,这是失败的,我希望它仍然像使用您的代码示例一样简单!谢谢你的回答,我的朋友!没有问题,请确保检查许可证协议的PrPoT包装和分发它。我们有一个内部的C++ WHIZ,所以我总是可以采取这条路线,如果必要的话。pskil.exe听起来像是我不仅可以在这里使用的东西,而且在其他一些情况下也可以使用。现在,我要试试。如果我遇到问题,我会去C++的方式!谢谢你的回答+1如果您可以以可控的方式终止应用程序(即,告诉它优雅地退出),这永远是比终止进程更好的选择,而终止进程只能作为最后的手段。