I'm using Wise Package Studio 7.0 SP2 on Windows XP.
I've got an MSI Wrapped EXE installation that goes about happily installing some files and then running one of the files from the installation which we can refer to as app.exe.
So on the "Execute Deferred" tab of the MSI Editor, I had to add the lines:
If Not Installed then
Execute Installed Program app.exe (Action)
End
This ensured that my app.exe would be run only on an installation and not during a modify/repair/removal. When app.exe runs, it conveniently adds itself to the system tray.
I'm looking for something that will do the reverse during a removal. I want to stop the app.exe process thus removing it from the system tray.
Currently my removal gets rid of all the files however the app.exe remains running and still shows up in the systems tray. I've looked at adding the conditional statement:
If REMOVE~="ALL" then
*remove the app from the systray!*
End
The conditional statement will let me do something only on a removal, however I'm not sure of the best approach to go about actually terminating the process. Is there an MSI command I can run that will let me do that? Should I write my own .exe that will do that?
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:
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.