程序只运行一个实例
2017-08-26 15:58
211 查看
本篇是参考了互联网上的资料,感谢慷慨的分享。 |
在开发过程中会遇到只允许运行一个实例的情况。 今天对这个问题进行探讨。 |
大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏、部分浏览器 等等! 让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前, 检查系统中是否已经设置了某些特定标志,是否创建了一些全局唯一的东西,或者让程序的多个实例都能看到的东西, 如果有则说明已经有一个实例在运行了,则当前程序通知用户如何如何,然后程序退出,当然方法有很多种,各有各的优缺点! |
创建互斥体 Mutex 法:
但是单纯的使用互斥体的话不能取得已经创建的实例窗口局柄,因此无法激活已经启动的实例窗口;
HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}")); if ( GetLastError() == ERROR_ALREADY_EXISTS ){ AfxMessageBox(_T("已经有一个实例正在运行中……")); CloseHandle(m_hMutex); m_hMutex = NULL; return FALSE; } //其他代码,比如对话框的创建及弹出等等 if (m_hMutex) { CloseHandle(m_hMutex); m_hMutex = NULL; }
方法二:
通过 FindWindow 进行窗口的查找,若发现则说明已经运行过一个实例,并将其窗口激活:
HWND hWnd = ::FindWindow(_T("#32770"), _T("DlgTest")); if (hWnd != NULL) { AfxMessageBox(_T("已经有一个实例正在运行中……")); ::ShowWindow(hWnd, SW_NORMAL); ::SetForegroundWindow(hWnd); return FALSE; }
此种方法不是很好,如果窗口标题改变了或者每个窗口实例的标题不一样,就找不到了!
方法三:
设置窗口属性 SetProp + EnumWindows 法!
1、加入全局变量的定义及枚举窗口函数:
TCHAR g_szPropName[] = _T("{12AA5160-5215-435b-AE3C-60C9E65615CE}"); HANDLE g_hValue = (HANDLE)9527; BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam) { HANDLE hProp = GetProp(hwnd, g_szPropName); if(hProp == g_hValue) { *(HWND *)lParam = hwnd; return FALSE; } return TRUE; }
2、窗口的枚举以及属性的添加:
//OnInitDialog() 中加入以下代码: HWND hPreWnd = NULL; ::EnumWindows(EnumWndProc, (LPARAM)&hPreWnd); if (hPreWnd != NULL) { AfxMessageBox(_T("已经有一个实例正在运行中……")); ::ShowWindow(hPreWnd, SW_NORMAL); ::SetForegroundWindow(hPreWnd); ExitProcess(0); return FALSE; } ::SetProp(m_hWnd, g_szPropName, g_hValue);
3、窗口属性的删除:
OnDestroy() 函数中加入以下代码: ::RemoveProp(m_hWnd, g_szPropName);
方法四
使用全局共享变量的共享节法实现单实例运行;
1、新建共享节:
#pragma data_seg("Shared") HWND hPreWnd = NULL; #pragma data_seg() #pragma comment(linker, "/Section:Shared,RWS")
2、OnInitDialog() 函数中加入以下代码:
if (hPreWnd == NULL) { hPreWnd = m_hWnd; } else { AfxMessageBox(_T("已经有一个实例正在运行中……")); ::ShowWindow(hPreWnd, SW_NORMAL); ::SetForegroundWindow(hPreWnd); ExitProcess(0); return FALSE; }
===================================================
- 方法五:
互斥体+自定义广播系统消息法;
1、系统消息的注册:
#define REG_MSG (_T("{7510EF00-BADA-48de-A6CE-5FBC817616DD}")) UINT WM_ACTIVE_MSG = ::RegisterWindowMessage(REG_MSG);
2、发现实例后,进行消息的广播:
InitInstance() 函数中添加如下代码: HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}")); if ( GetLastError() == ERROR_ALREADY_EXISTS ){ AfxMessageBox(_T("已经有一个实例正在运行中……")); CloseHandle(m_hMutex); m_hMutex = NULL; DWORD dwRecipients = BSM_APPLICATIONS; ::BroadcastSystemMessage(BSF_NOHANG, &dwRecipients, WM_ACTIVE_MSG, 0, 0); return FALSE; } //其他窗口创建之类的代码 if (m_hMutex) { CloseHandle(m_hMutex); m_hMutex = NULL; }
3、窗口类中全局变量的作用域扩展:
extern UINT WM_ACTIVE_MSG;
4、窗口类中自定义消息的响应:
afx_msg LRESULT OnActiveMsg(WPARAM wParam, LPARAM lParam); ON_REGISTERED_MESSAGE(WM_ACTIVE_MSG, &CDlgTestDlg::OnActiveMsg) LRESULT CDlgTestDlg::OnActiveMsg(WPARAM wParam, LPARAM lParam) { ::ShowWindow(m_hWnd, SW_NORMAL); ::SetForegroundWindow(m_hWnd); return TRUE; }
相关文章推荐
- 使Qt程序只能运行一个实例的3种方法
- delphi程序只允许运行一个实例的三种方法
- 【转】delphi程序只允许运行一个实例的三种方法:
- VC 实现程序只运行一个实例
- 让你的程序只运行一个实例(二)
- Qt程序只运行一个实例
- C# 让程序只能运行一个实例
- C#程序只允许运行一个实例的解决方案
- 用C#给程序加启动画面并只允许一个应用程序实例运行
- 保证系统中只运行一个程序实例
- 互斥运行一个程序实例
- WPF程序只有一个实例运行
- 让程序只运行一个实例的四种方法
- 让程序只运行一个实例的简单实用的方法
- 程序只运行一个实例(四)
- 让Java程序只运行一个实例
- 让程序只运行一个实例的方法总结[转]
- 只运行一个程序实例
- 【转】delphi程序只允许运行一个实例的三种方法:
- 确保程序只有一个实例在运行