代码之家  ›  专栏  ›  技术社区  ›  Mat Nadrofsky

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

  •  4
  • Mat Nadrofsky  · 技术社区  · 16 年前

    我在Windows XP上使用的是Wise Package Studio 7.0 SP2。

    我有一个msi包装的exe安装程序,它很乐意安装一些文件,然后运行安装中的一个文件,我们可以将其称为app.exe。

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

    If Not Installed then
      Execute Installed Program app.exe (Action)
    End
    

    这确保了我的app.exe可以运行 只有 在安装过程中,而不是在修改/修复/删除过程中。当app.exe运行时,它可以方便地将自己添加到系统托盘中。

    我在找一些可以在移除过程中反转的东西。我想停止app.exe进程,从而将其从系统托盘中删除。

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

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

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

    4 回复  |  直到 14 年前
        1
  •  2
  •   saschabeaumont    16 年前

    6个月前,我们使用vbscript操作来做同样的事情,然后就在sp3发布时,objprocess.terminate()函数拒绝在某些计算机上工作。不管我们做了什么,它都冻结了。这发生在我们大约10%的测试机器上,因此我们不得不找到一个替代的解决方案(谁知道它可能冻结了多少客户!)

    我的第一个发现是内置(自Windows2000以来)命令taskkill 如: TASKKILL /IM app.exe /F 但是,由于这似乎使用了类似于我们在vbscript中使用的杀死进程的方法,所以该方法也会失败。

    所以现在我们使用 pskill.exe 工具来自SysInternals,您需要使用命令行开关来支持许可协议提示,但除此之外,它是杀死正在运行的exe的最简单的方法。

    当然,最好的解决方案是建立你自己的EXE或DLL来做它,如果你碰巧知道一点C++的话;

        2
  •  1
  •   Edward Brey    15 年前

    仅仅终止进程是不够的,因为这并不能清除Windows通知区域(但是,当鼠标下一次悬停在上面时,Windows将清除一个没有匹配进程的图标)。然而,突然终止应用程序的另一个原因通常最好保留用于调试。不幸的是,一个更合适的解决方案也更为复杂。您可以在应用程序中创建一个命名事件,并注册一个回调方法,以便在设置该方法时调用。回调将关闭应用程序。然后编写一个自定义操作,设置事件并等待进程终止。

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

        3
  •  0
  •   dim    16 年前

    可以将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
    
        4
  •  0
  •   RobH    14 年前

    如果你的app.exe是在内部创建的,你可以添加一个命令行,告诉它终止当前正在运行的命令行。当给定该命令行时,它将向该程序的第一个实例发送一条消息或一些东西,告诉它退出,然后挂起等待,直到该程序的第一个实例实际终止。然后,安装程序就可以用kill开关运行程序,并知道当kill开关实例返回时,它的原始实例就不存在了。

    推荐文章