1

My laptop has a button to run calculator, but each time I press it, it spawns a new process instead of focusing on an existing one. I've decided to write a small application to focus on calculator's window if it exists or spawn a new one.

#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <WtsApi32.h>

HWND find_top_window(DWORD pid)
{
    std::pair<HWND, DWORD> params = { 0, pid };

    BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL
    {
        auto pParams = (std::pair<HWND, DWORD>*)(lParam);

        DWORD processId;
        if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second)
        {
            SetLastError(-1);
            pParams->first = hwnd;
            return FALSE;
        }

        return TRUE;
    }, (LPARAM)&params);

    if (!bResult && GetLastError() == -1 && params.first)
    {
        return params.first;
    }

    return 0;
}

///
int main(int argc, char* argv[])
{
    LPCWSTR szProcessName = TEXT("Calculator");
    WTS_PROCESS_INFO* pWPIs = NULL;
    DWORD dwProcCount = 0;

    if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
    {
        for (DWORD i = 0; i < dwProcCount; i++)
        {
            if (wcsstr(pWPIs[i].pProcessName, szProcessName) != NULL)
            {
                std::cout << "Found!\npid: " << pWPIs[i].ProcessId << "\n";

                HWND hWnd = find_top_window(pWPIs[i].ProcessId);

                std::cout << "hwnd:" << hWnd << "\n";

                if (hWnd != 0)
                {
                    ShowWindow(hWnd, SW_SHOW);
                    //ShowWindow(hWnd, SW_RESTORE);
                }

                break;
            }
        }
    }

    if (pWPIs)
    {
        WTSFreeMemory(pWPIs);
        pWPIs = NULL;
    }

    return 0;
}

For some reason, it fails to ShowWindow - window is not being shown. Need help on this one - I do not know why it fails.

CorellianAle
  • 645
  • 8
  • 16
  • Rather than enumerating processes, why not just use `FindWindow(NULL, "Calculator")` instead? Also, `ShowWindow()` may not be enough. Look at [`SetForegroundWindow()`](https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setforegroundwindow) (but note the many restrictions it has) or [`SwitchToThisWindow()`](https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-switchtothiswindow). – Remy Lebeau Oct 25 '18 at 21:07
  • @RemyLebeau The idea was to search for an executable, not a window's title. – CorellianAle Oct 25 '18 at 21:19
  • @RemyLebeau `SetForegroundWindow(HWND) did the trick. – CorellianAle Oct 25 '18 at 21:20
  • AFAIR the `EnumWindows()` should be called in a loop until it returns `FALSE`. –  Oct 25 '18 at 21:23
  • @j.d: The lambda *is* called for every top-level window, and the 'loop' breaks, when a match is found and `FALSE` is returned. `EnumWindows` runs that loop. You don't need to call `EnumWindows` in a loop. You know that already, since `EnumWindows` doesn't allow for the current state to be passed as an argument, so `EnumWindows` has no way to determine, where to start. – IInspectable Oct 26 '18 at 08:39

0 Answers0