0

Window APIs are new for me. I am trying to find the number of windows that are open from windows desktop application. I wanted to open only one instance of an application.

I have my application abc.exe. If user tries to open the abc.exe application for the first time then the abc.exe application will open normally. But, if abc.exe application is already open and the usser tries to open it again then it should give an already open instance of Application.

I am able to get an already open instance with help from the below code in specific condition.

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
HWND *retHwnd = (HWND *)lParam;

if (*retHwnd) {
    return FALSE;
}

DWORD procID = 0;
auto threadID = GetWindowThreadProcessId(hwnd, &procID);

auto handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, procID);

QString fileName;
if (handle) {
    TCHAR filename[FILENAME_MAX];
    auto len = GetModuleFileNameEx(handle, NULL, filename, FILENAME_MAX);

    fileName = QFileInfo(QString::fromWCharArray(filename, len)).fileName();
    if (GetLastApplicationName() == fileName) {
        *retHwnd = hwnd;
    }

    CloseHandle(handle);
}

return TRUE;
}

void ShowExistingInstance() {
HWND hwnd = 0;
auto res = EnumWindows(&EnumWindowsProc, (LPARAM)&hwnd);

    if (hwnd) {
        ShowWindow(hwnd, SW_MINIMIZE);
        ShowWindow(hwnd, SW_MINIMIZE);
        ShowWindow(hwnd, SW_RESTORE);
    }
}

However, I am not getting first instance of the application if two windows are open from the application.

Below I mention two situations. In the first situation the code works fine, and in the second situation the code the code does not work fine.

1) Get already open instance of application

Steps:

a. User clicks on abc.exe application icon.

b. Main window is open for example its name is mainWindow1.

c. Restore-down or Minimize mainWindow1

d. User clicks abc.exe again using the application icon

e. Here I am getting mainWindow1, and it is correct.

2) Does not get already open instance of application

Steps:

a. User clicks on abc.exe application icon.

b. Main window is open for example its name is mainWindow1.

c. User opens another window from the current application for example its name is mainWindow2. (mainWindow1 is not parent of mainWindow2).

d. Restore-down or Minimize mainWindow1 (here mainWindow2 is also minimized or Restore- down automatically w.r.t mainWindow1)

e. User clicks abc.exe again using the application icon.

f. Here I am getting mainWindow2 instead of mainWindow1.

I wanted some kind of guide line for windows API, which is help me to find the Hwnd of Mainwidnow1 in second situation.

Yash
  • 9
  • 3
  • You can monitor `Win32_ProcessStartTrace` and `Win32_ProcessStopTrace` to detect start and stop of applications. Here is an example of [`Win32_ProcessStopTrace`](https://stackoverflow.com/a/39704027/3110834). However, if you have the source code for `abc.exe`, you need to make it single instance [this way](https://stackoverflow.com/a/33028650/3110834). – Reza Aghaei Feb 20 '19 at 17:53
  • Thank you Reza Aghaei for guide line. – Yash Feb 20 '19 at 18:59

1 Answers1

0

I got my functionality with help of below code

BOOL isMainWindow(HWND handle) {
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    HWND *retHwnd = (HWND *)lParam;

    if (*retHwnd) {
       return FALSE;
    }

    DWORD procID = 0;
    auto threadID = GetWindowThreadProcessId(hwnd, &procID);

    if (!isMainWindow(hwnd)) {
        return TRUE;
    }

    auto handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, procID);

   QString fileName;
   if (handle) {
        TCHAR filename[FILENAME_MAX];
        auto len = GetModuleFileNameEx(handle, NULL, filename, FILENAME_MAX);

        fileName = QFileInfo(QString::fromWCharArray(filename, len)).fileName();
        if (GetLastApplicationName() == fileName) {
            *retHwnd = hwnd;
        }

        CloseHandle(handle);
    }

return TRUE;
}
void ShowExistingInstance() {
    HWND hwnd = 0;
    auto res = EnumWindows(&EnumWindowsProc, (LPARAM)&hwnd);

   if (hwnd) {
       ShowWindow(hwnd, SW_MINIMIZE);
       ShowWindow(hwnd, SW_MINIMIZE);
       ShowWindow(hwnd, SW_RESTORE);
   }
 }
Yash
  • 9
  • 3