windows c++程序单实例运行 - 进程互斥

单实例程序

单实例运行程序其实很常见,比如微信,QQ。这些程序重复打开是无效的,这种程序我们就称之为单实例程序。

单实例程序与单例模式区别

单例模式是以一个程序(进程)作为系统,在这个系统里的某个单例类只能有一个实例。而单实例程序的系统是整个操作系统,也就是在这个系统里只有一个实例。它们的实现方式不同,单例模式可以使用语言特性防止其创建实例。而单实例程序的实现可以有很多种方式,我们在本篇文章只介绍其中一种。

进程互斥锁

这种方式就是利用Win32API提供的CreateMutex函数创建进程间的互斥锁,创建了进程互斥体,如果打开了第二个程序,检测到同样的互斥体对象名,则创建不成功。

CreateMutex

CreateMutex的声明如下:

WINBASEAPI HANDLE WINAPI CreateMutexW (
    LPSECURITY_ATTRIBUTES lpMutexAttributes, 
    WINBOOL               bInitialOwner, 
    LPCWSTR               lpName
);

参数:

  • lpMutexAttributes:指向struct SECURITY_ATTRIBUTES 的指针。 如果此参数为 NULL,则子进程无法继承句柄。

  • bInitialOwner:如果此值为 TRUE ,并且调用方创建了互斥体,则调用线程获取互斥体对象的初始所有权。 否则,调用线程不会获取互斥体的所有权。

  • lpName:互斥体对象的名称。

返回值:

  • 如果函数成功,则返回值是新创建的互斥体对象的句柄。
  • 如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。如果互斥体是命名互斥体,并且此函数调用之前存在对象,则返回值是现有对象的句柄, 并且 GetLastError 函数返回 ERROR_ALREADY_EXISTS。

函数实现

bool isProgramRunning(){
    HANDLE hMutex = nullptr;
    hMutex = CreateMutexW(nullptr, false, L"MutexObjName");
    if (hMutex){
        if (ERROR_ALREADY_EXISTS == ::GetLastError()){
            MessageBoxW(nullptr, L"Failed to start the program. An instance of this program is already running.", L"Error", MB_OK|MB_ICONSTOP);
            CloseHandle(hMutex);
            return true;
        }
    }
    return false;
}

代码实战

#define UNICODE
#include <iostream>
#include <Windows.h>
using namespace std;

BOOL isProgramRunning() {
    HANDLE hMutex = NULL;
    hMutex = ::CreateMutexW(NULL, FALSE, L"WinApp");
    if (hMutex) {
        if (ERROR_ALREADY_EXISTS == ::GetLastError()) {
            MessageBoxW(nullptr, L"Failed to start the program. An instance of this program is already running.", L"Error", MB_OK | MB_ICONSTOP);
            CloseHandle(hMutex);
            return TRUE;
        }
    }
    return FALSE;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pCmdLine, int nCmdShow) {
    if (isProgramRunning()) {
        return -1;
    }

    const wchar_t* CLASS_NAME = L"Window Class";
    WNDCLASSW wc = { };
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    RegisterClass(&wc);

    HWND hwnd = CreateWindowExW(
        0, CLASS_NAME, L"Window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
        NULL, NULL, hInstance, NULL
    );

    if (hwnd == NULL) {
        return 0;
    }
    ShowWindow(hwnd, nCmdShow);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

效果:

windows c++程序单实例演示 - 进程互斥

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

orbitgw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值