指定exeのウインドウにWM_CLOSEを投げる

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

アプリのデバッグで、特定のウインドウメッセージ(WM_XXXXX)を受け取ったときの動作を見たいときがあった。

Windowsサービスのプログラムだと、以前の記事で調べたように、sc controlコマンドで好きなメッセージ(サービスコトロール)を送れるが、特定のウインドウに好きなWMメッセージを送れるようなコマンドが見当たらなかった。

デバッグ用に、そういうのを作ってみる。

コード

とりあえず、Notepad.exeにWM_CLOSEを送ってウインドウを閉じるプログラムを作ってみた。

https://github.com/tera1707/WM_MessageSender

// WM_MessageSender.cpp : アプリケーションのエントリ ポイントを定義します。
//

#include "framework.h"
#include "WM_MessageSender.h"
#include <psapi.h>
#include <string>
#include <filesystem>

// グローバル変数:
HINSTANCE hInst;                                // 現在のインターフェイス

BOOL CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);
void OnButtonClicked();
BOOL OnFindWindow(HWND hWnd, LPARAM lp);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    hInst = hInstance;

    // ダイアログの名前と、プロシージャを指定してDialogBoxを開く
    DialogBox(hInst, L"WM_MessageSenderMain", NULL, (DLGPROC)MyDlgProc);

    return (int)0;
}

BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg) {
    case WM_COMMAND:
        switch (LOWORD(wp)) {
        case IDOK:
            EndDialog(hDlg, IDOK);
            return TRUE;
        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            return TRUE;
        case IDC_BUTTON1:
            OnButtonClicked();
            break;
        }
        return FALSE;
    }
    return FALSE;
}

//std::vector 

void OnButtonClicked()
{
    EnumWindows((WNDENUMPROC)OnFindWindow, 0);
}

BOOL OnFindWindow(HWND hWnd, LPARAM lp)
{
    WCHAR dest[MAX_PATH] = { 0 };

    // プロセスID
    DWORD processID = NULL;
    GetWindowThreadProcessId(hWnd, &processID);

    // プロセスハンドル
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
    if (!hProcess)
        return false;

    // モジュールハンドル
    HMODULE hModule = NULL;
    DWORD dummy = 0;
    if (!EnumProcessModules(hProcess, &hModule, sizeof(HMODULE), &dummy))
        return false;

    // ファイル名(フルパス)
    memset(dest, 0, MAX_PATH - 1);
    if (!GetModuleFileNameEx(hProcess, hModule, dest, MAX_PATH - 1))
        return false;

    CloseHandle(hProcess);

    auto procPath = std::wstring(dest);
    std::filesystem::path filepath = procPath;

    if (filepath.filename() == L"Notepad.exe")
    {
        OutputDebugString(L"あった!");

        PostMessage(hWnd, WM_CLOSE, 0, 0);
    }

    OutputDebugString((procPath + L"\r\n").c_str());

    return true;
}

参考

ダイアログベースのC++ひな型

https://qiita.com/tera1707/items/003961a385e6bbf8a160