How to stop a running process during an MSI based un-install?

▼魔方 西西 提交于 2019-12-01 18:39:45

6 months ago we were using VBScript actions to do the same thing, then right around the time that SP3 was released the objProcess.Terminate() function just refused to work on some machines. No matter what we did, it just froze. This happened on around 10% of our test machines so we were forced to find an alternative solution (who knows how many customers it might have frozen on!)

My first discovery was the inbuilt (since Windows 2000) command TASKKILL eg: TASKKILL /IM app.exe /F but as that seems to use similar means of killing a process as we used in VBScript, that method would also fail.

So now we're using the pskill.exe tool from sysinternals, you need to use a command line switch to supress the license agreement prompt but other than that, it's been the most foolproof way of killing a running EXE that I've found.

Of course the best solution would be to build your own EXE or DLL to do it should you happen to know a little C++ ;)

Just terminating processes isn't sufficient, since that doesn't clean up the Windows Notification Area (however, Windows will clean up an icon with no matching process when the mouse next hovers over in). Yet one more reason why terminating apps abruptly is generally best reserved for debugging. Unfortunately, a more proper solution is also more involved. You could create a named event in the app and register a callback method to be called when it is set. The callback would close the app. Then you'd write a custom action that set the event and waited until process terminated.

If you need to support cancellation (e.g. the user is prompted that he has unsaved changes and decides not to cancel), you may use another named event to indicate that, so the custom action may wait for either the process to end or a cancellation event, whichever comes first.

You can insert VBscript elements into the MSI as custom actions. Something like this should do the job:

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

If your app.exe was created in house, you could add a command line that tells it to kill the one that's currently running. When given that command line, it would send that first instance of the program a message or something that tells it to quit and then hang around just waiting until that first instance of the program has actually terminated. The installer would then be able to run the program with the kill switch and know that the original instance of it is gone when the kill switched instance has returned.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!