views:

111

answers:

6

I have a CLI/C++ based install application which needs to close another app I've written, replace the application's .exe and dlls and the re-run the executable.

First of all I need to close that window along the following lines:

HWND hwnd = FindWindow(NULL, windowTitle);
if( hwnd != NULL )
{
    ::SendMessage(hwnd, (int)0x????, 0, NULL);
}

I.e. find a matching window title (which works) ...but then what message do I need send the remote window to ask it to close?

...or is there a more .net-ish way of donig this without resorting to the windows API directlry?

Bare in mind that I'm limited to .net 2.0

+4  A: 

WM_CLOSE?

Andreas Rejbrand
That got it - thanks
Jon Cage
+1  A: 

WM_CLOSE, or 0x0010

Paul Williams
A: 

UPDATE

Use WM_CLOSE. I was wrong.

clocKwize
Nope. WM_CLOSE is correct. WM_QUIT is for terminating a message loop. Most traditional apps Post the WM_QUIT to themselves in order to exit the primary message loop when the main toplevel window is destroyed. That sequence is typically initiated by WM_CLOSE.
Adrian McCarthy
Terminating the message loop generally causes the application to exit right? Wm close might not exit the application, just that window. I could of course be wrong though :)
clocKwize
The problem is, you don't know which message loop you're terminating. What if the app is showing a modal dialog? You might just be putting the app into a bad state, without saving user data. I retract what I said about `WM_CLOSE`. The right thing to use is `WM_QUERYENDSESSION` and `WM_ENDSESSION`.
Adrian McCarthy
From MSDN: "The WM_QUIT message is not associated with a window and therefore will never be received through a window's window procedure. It is retrieved only by the GetMessage or PeekMessage functions. Do not post the WM_QUIT message using the PostMessage function."
Adrian McCarthy
+1  A: 

In case anyone wants to follow the more .net-ish way of donig things, you can do the following:

using namespace System::Diagnostics;

array<Process^>^ processes = Process::GetProcessesByName("YourProcessName");
for each(Process^ process in processes)
{
    process->CloseMainWindow(); // For Gui apps
    process->Close(); // For Non-gui apps
}
Jon Cage
+1  A: 

Guidelines from MSDN

  1. Send WM_QUERYENDSESSION with the lParam set to ENDSESSION_CLOSEAPP.
  2. Then send WM_ENDSESSION with the same lParam.
  3. If that doesn't work, send WM_CLOSE.
Adrian McCarthy
+2  A: 

You can call WM_CLOSE using SendMessage.

[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

See http://boycook.wordpress.com/2008/07/29/c-win32-messaging-with-sendmessage-and-wm_copydata/ for code sample.

Brian