views:

1530

answers:

3

Hey all,

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?

A: 

Hi Mat,

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
Froosh
it's not a reliable solution, from my experience this fails on a significant number of machines running XP SP3
sascha
Based on what sascha has stated, I wish it was still as simple as using your code sample! Thanks for the answer though my friend!
Mat Nadrofsky
No problems, be sure to check the license agreement for pskill when packaging and distributing it.
Froosh
+2  A: 

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++ ;)

sascha
We've got an in-house C++ whiz so I can always take that route if necessary. pskil.exe sounds like something I might not only be able to utilize here, but in a few other situations as well. For now, I'll try that. If I run into issues, I'll go the C++ way! Thanks for the answer!
Mat Nadrofsky
No problem Mat, happy to help!
sascha
+1  A: 

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.

Edward Brey
+1 If you can terminate an application in a controlled way (i.e. telling it to exit gracefully) is always a better option than just killing the process, which should only be done as a last resort.
CodeSavvyGeek