Shutting Down MSN Messenger
Posted by daniel on 2003-09-16 05:57:20
At some point in most MSN Messenger applications, you may want to shut down Messenger, or restart it. This could be to apply a patch, or to make Messenger run its shut down routine, like updating the list cache, or removing the systray icon. MSN Messenger has a cross application window message method to make it exit, this is commonly used by its installer. When you install an update the current version is closed so it can overwrite the files.
An obvious method of shutting Messenger down would be to just use TerminateProcess, this method is very forceful and Messenger won't perform its shutdown routine. Before you perform this kind of termination, its best to try the cross application windows message method. This involves sending a custom window message to the Messenger system window "MSNHiddenWindowClass", which is just an always open window for things like receiving events for the systray icon.
You may have before seen a message pop up telling you that you need to close applications that are using MSN Messenger, like Hotmail in Internet Explorer, Outlook Express. The window message method cannot ignore this, therefore you WILL need to forcefully terminate Messenger. You should kill all instances of the Messenger typelib to prevent the message beforehand, otherwise you can get the user to close those applications.
First, lets look at the window message method. You need to register the message "TryMsnMsgrShutdown", and send it to the window with the class name "MSNHiddenWindowClass".
code:
Private Sub GracefullShutdown(bShowCloseMsg As Boolean)
Dim hWnd As Long, lMsg As Long
hWnd = FindWindow("MSNHiddenWindowClass", vbNullString)
lMsg = RegisterWindowMessage("TryMsnMsgrShutdown")
Call SendMessage(hWnd, lMsg, CLng(bShowCloseMsg) + 1, 0)
End Sub
First it gets the handle to the hidden window, then it gets the ID for the custom window message, and last of all it sends the message to the hidden window. If wParam is zero then, if applicable, the message saying to close all applications using Messenger will be shown, if wParam is one then the message will not be shown. Unfortunatly, I dont see a way of it letting us know if the shutdown was successfull, so you then should forcefully shut it down. Its best to wait a second or two to let it do what it needs to do - if it shutdown successfully.
Here is how to forcefully shut it down, by terminating the Messenger process.
code:
Private Sub ForcefullShutdown()
Dim hWnd As Long, lProcessID As Long, lProcess As Long
hWnd = FindWindow("MSNHiddenWindowClass", vbNullString)
Call GetWindowThreadProcessId(hWnd, lProcessID)
lProcess = OpenProcess(0, False, lProcessID)
Call TerminateProcess(lProcess, 0)
Call CloseHandle(lProcess)
End Sub
Again, it finds the hidden window, because it is always open. It then puts the process ID for that window into a var, creates a process handle to use to be terminated, terminates the process. And closes the process handle, freeing up resources.
Here are the API declarations for those used.
code:
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long