Jump to content

There can only be one (instance of your program)


Josh
 Share

Recommended Posts

This code will check to see if your program is already running, and activate the window and bring it to the front if it is. If the window is minimized, it will be restored.

String title = "My Program";
#define ERROR_ALREADY_RUNNING 1

int main(int argc, const char* argv[])
{
#ifdef _WIN32
	auto hwnd = FindWindowA(NULL, title.c_str());
	if (hwnd)
	{
		if (IsIconic(hwnd)) ShowWindow(hwnd, SW_RESTORE);
		SetForegroundWindow(hwnd);
		SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
		SetActiveWindow(hwnd);
		SetFocus(hwnd);
		return ERROR_ALREADY_RUNNING;
	}
#endif

There Can Be Only One Highlander GIF

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Maybe you should use the common mutex approach:

m_singleInstanceMutex = CreateMutex(NULL, TRUE, L"Some unique string for your app");
if (m_singleInstanceMutex == NULL || GetLastError() == ERROR_ALREADY_EXISTS) {
    HWND existingApp = FindWindow(0, L"Your app's window title");
    if (existingApp) SetForegroundWindow(existingApp);
    return FALSE; // Exit the app. For MFC, return false from InitInstance

 

 

  • Upvote 2
  • Intel® Core™ i7-8550U @ 1.80 Ghz 
  • 16GB RAM 
  • INTEL UHD Graphics 620
  • Windows 10 Pro 64-Bit-Version
Link to comment
Share on other sites

  • 7 months later...

Here is a function that will check if an app is open and if it is, it will send some data to the other application:

bool CheckIfOpen(shared_ptr<Window> source, const WString& appid, const WString& apptitle, shared_ptr<Buffer> data)
{
    const int DATA_ID = 345934;// whatever...
    auto m_singleInstanceMutex = CreateMutexW(NULL, TRUE, appid.c_str());
    if (m_singleInstanceMutex == NULL or GetLastError() == ERROR_ALREADY_EXISTS)
    {
        HWND hwnd = FindWindowW(0, apptitle.c_str());
        if (hwnd and data)
        {
            COPYDATASTRUCT copydata;
            copydata.dwData = DATA_ID;
            copydata.cbData = data->GetSize();
            copydata.lpData = data->Data();
            LPARAM srchwnd = 0L;
            if (source) srchwnd = (LPARAM) source->GetHandle();
            SendNotifyMessageW(hwnd, WM_COPYDATA, srchwnd, (LPARAM) &copydata);
        }
        return false; // Exit the app. For MFC, return false from InitInstance
    }
    return true;
}

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

This is the best way to do this:

struct EnumWindowInfo
{
    int messageid;
    WString procname, title;
    shared_ptr<Buffer> data;
    shared_ptr<Window> source;
    bool result;
};

BOOL CALLBACK EnumWindowsProc(_In_ HWND hwnd, _In_ LPARAM lParam)
{
    const int MAX_NAME = 2048;
    auto info = (EnumWindowInfo*)lParam;
    WString path;
    path.resize(MAX_NAME);
    std::fill(path.begin(), path.end(), 0);
    int sz = GetWindowTextW(hwnd, (LPWSTR)path.c_str(), path.size());
    if (0 == sz)
    {
        auto err = GetLastError();
        return true;
    }
    path.resize(sz);
    //Print(path); 
    if (path != info->title) return true;
    DWORD lpdwProcessId = 0;
    auto threadID = GetWindowThreadProcessId(hwnd, &lpdwProcessId);
    HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, TRUE, lpdwProcessId);
    path.resize(MAX_NAME);
    auto len = GetModuleFileNameExW(proc, NULL, (LPWSTR)path.c_str(), path.size());
    CloseHandle(proc);
    path.resize(len);
    if (StripDir(path) == info->procname)
    {
        COPYDATASTRUCT copydata;
        copydata.dwData = info->messageid;
        copydata.cbData = info->data->GetSize();
        copydata.lpData = info->data->Data();
        HWND srchwnd = 0L;
        if (info->source) srchwnd = info->source->GetHandle();
        ShowWindow(hwnd, SW_RESTORE);
        SendMessageW(hwnd, WM_COPYDATA, (LPARAM)srchwnd, (LPARAM)&copydata);
        SetForegroundWindow(hwnd);
        SetActiveWindow(hwnd);
        SetFocus(hwnd);
        info->result = true;
        return false;
    }
    return true;
}

bool SendWindowData(shared_ptr<Window> source, const WString& title, const WString& processname, const int messageid, shared_ptr<Buffer> data)
{
    EnumWindowInfo info;
    info.title = title;
    info.result = false;
    info.procname = processname;
    info.data = data;
    info.messageid = messageid;
    EnumWindows(EnumWindowsProc, (LPARAM)&info);
    return info.result;
}

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...