using sendmessage to send wm_close to another process
Asked Answered
H

4

5

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?

Hematology answered 23/3, 2011 at 7:43 Comment(3)
Why are you opening the process? That seems unnecessary. Error 6 means an invalid handle. You shouldn't call CloseHandle on a window handle. You don't need to tidy up the window handle, it's not a HANDLE.Amey
i was trying something else, so opening process is part of that. And i know error 6. You shouldn't call CloseHandle on a window handle --> thanks alot for this.Hematology
Sending the WM_CLOSE message to the main form of an app does result in it closing, if that window responds to WM_CLOSE. I can't imagine what you are doing wrong. My recommendation is to use Spy++ to check that you have located the right window handle.Amey
T
2

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.

Telephoto answered 23/3, 2011 at 8:16 Comment(3)
IsWindow() returns true, doesn't it mean i've a valid window?Hematology
@rplusg: IsWindow tells you it is a valid window handle, not more. It can be that the application has got several top level windows, maybe not visible. And you may not close the right one.Telephoto
even i'm not sure what is the problem, but enumwindows has given my desired results. Thanks patriiice, marking your answer as final.Hematology
J
3

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).

Joselow answered 11/1, 2012 at 3:15 Comment(0)
T
2

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.

Telephoto answered 23/3, 2011 at 8:16 Comment(3)
IsWindow() returns true, doesn't it mean i've a valid window?Hematology
@rplusg: IsWindow tells you it is a valid window handle, not more. It can be that the application has got several top level windows, maybe not visible. And you may not close the right one.Telephoto
even i'm not sure what is the problem, but enumwindows has given my desired results. Thanks patriiice, marking your answer as final.Hematology
L
0

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.

Laborsaving answered 23/3, 2011 at 8:17 Comment(2)
WM_DESTROY and WM_NCDESTROY also doesn't work. DestroyWindow() also returns false.Hematology
WM_DESTROY and WM_NCDESTROY can't work, they are notifications.Amey
P
0

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.

Paranymph answered 28/11, 2023 at 21:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.