5

I have a C++/CLI 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

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Jon Cage
  • 36,366
  • 38
  • 137
  • 215
  • Has the app you're trying to close already shipped? If not, you could build in a custom message just for this purpose. – Adrian McCarthy Aug 23 '10 at 15:42
  • Why bother when there's already the windows messages? – Jon Cage Aug 23 '10 at 15:52
  • 1
    Because `WM_CLOSE` doesn't really tell an application to quit. It tells a window to close. Many apps quit when the main window closes, but some don't. They might have other windows open, or they might continue to run in the background. By defining a custom message, you can ensure that the application does exactly what you need it to do without overloading an already well-defined message. – Adrian McCarthy Aug 23 '10 at 16:08
  • Thanks - that's worth knowing :) – Jon Cage Aug 23 '10 at 18:12

5 Answers5

5

WM_CLOSE?

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • 1
    This answer needs improvement. Link-only answers are not good answers; consider including the substantive details in your answer. – rory.ap Jan 09 '18 at 17:22
3

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
  • 25,523
  • 18
  • 82
  • 173
2

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
  • 45,555
  • 16
  • 123
  • 175
1

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
  • 36,366
  • 38
  • 137
  • 215
-1

UPDATE

Use WM_CLOSE. I was wrong.

Michael Baldry
  • 1,990
  • 2
  • 14
  • 28
  • 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 Aug 23 '10 at 15:41
  • 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 :) – Michael Baldry Aug 23 '10 at 16:11
  • 1
    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 Aug 24 '10 at 20:04
  • 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 Aug 25 '10 at 17:05