rplusg
rplusg

Reputation: 3446

using sendmessage to send wm_close to another process

I want to send wm_close to another process, with which i want end that process safely.

int _tmain(int argc, _TCHAR* argv[])
{

    DWORD SetOfPID;
    SetOfPID = GetProcId(_T("abc.exe"));  //this will return pid
    HANDLE h = OpenProcess(PROCESS_ALL_ACCESS,false, SetOfPID);

    HWND hwnd = ::GetTopWindow(NULL);
    while(hwnd)
    {
        DWORD pid;
        DWORD dwThreadId = ::GetWindowThreadProcessId(hwnd, &pid);
         if(pid == SetOfPID)
         {    
              break;
         }
         hwnd = ::GetNextWindow(hwnd, GW_HWNDNEXT);
    }
    //DestroyWindow(hwnd);
    bool temp = IsWindow(hwnd); **//this gives true**
    LRESULT res = ::SendMessage(hwnd, WM_CLOSE, NULL, NULL);
    DWORD err = GetLastError(); **//this gives 6**
    CloseHandle(hwnd);
    CloseHandle(h);
    return 0;
}

this piece of code looks good, but the target process doesn't terminate, can somebody help me?

Upvotes: 5

Views: 28605

Answers (4)

Paul Hutchinson
Paul Hutchinson

Reputation: 1728

I found an example of sending messages to a different processes window from Tonto that uses a different method of finding the window to send to.

It uses EnumWindows() to walk over the windows. When it finds the one with the matching PID it sends the message.

Here is a slightly modified version (the same but sends a sends the WM_CLOSE):

#include <windows.h>
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    DWORD processId;
    GetWindowThreadProcessId(hwnd, &processId);

    if(lParam == processId)
        PostMessage(hwnd, WM_CLOSE, 0, 0);
    return TRUE;
}

int main(int argc, char *argv[])
{
    STARTUPINFO         siInfo;
    PROCESS_INFORMATION piInfo;
 
    ZeroMemory(&siInfo, sizeof(siInfo));
    ZeroMemory(&piInfo, sizeof(piInfo));
 
    CreateProcess
        ("C:\\WINDOWS\\Notepad.exe", "", 0, 0, 
        FALSE, CREATE_DEFAULT_ERROR_MODE, 0, 0, 
        &siInfo, &piInfo);
 
    WaitForSingleObject(piInfo.hProcess, 1000);
    EnumWindows(&EnumWindowsProc, piInfo.dwProcessId);
    return 0;
}

This starts C:\WINDOWS\Notepad.exe waits a second and then sends the WM_CLOSE.

This opened notepad and then closed it. When I tried it with my program instead it also worked, so I think you are having problems find the right window to send the message to.

NOTE that there is no error checking in this example.

Upvotes: 0

mattjs
mattjs

Reputation: 31

I would attempt to close a (Process with) Window(s) in the following order:

  1. WM_CLOSE

  2. WM_QUIT

  3. WM_DESTROY

  4. TerminateProcess().

Just my take as I am handling (disabling) WM_CLOSE for a Window and having difficulty distinguishing between User Close and close messages send by another master task. WM_QUIT seems to resolve my problem without using a custom WM_APP_CLOSE of my own. TerminateProcess is very much a last resort unclean exit to be avoided at all costs (it may leave handles (e.g. COM etc) and memory etc unfreed).

Upvotes: 3

Ferenc Deak
Ferenc Deak

Reputation: 35448

If the application does not process WM_CLOSE the DefWindowProc should handle this (by gracefully closing the application), however if the application is handling WM_CLOSE then it simply can choose to ignore it. Try sending the WM_DESTROY and WM_NCDESTROY messagees instead.

Upvotes: 0

pagra
pagra

Reputation: 665

Are you sure that the window you are finding is the correct one? You can check easily with Spy++. Moreover, when searching for a window, I think it's better to use EnumWindows. I'm not sure your method is correct.

Upvotes: 2

Related Questions