最近,一个公司项目要求防止程序多开,采用了几种方法,效果还行。
一、使用Mutex
- HANDLE hObject = ::CreateMutex(NULL,FALSE, _T("Mutex20100731"));
- if(GetLastError() == ERROR_ALREADY_EXISTS)
-
{ -
CloseHandle(hObject); -
MessageBox(NULL, _T("应用程序已经在运行!"), _T("提示"), MB_ICONERROR|MB_OK); -
return FALSE; -
}
二、使用窗口属性
lParam可由EnumWindows的第二个参数传递。
- CString g_propName = _T("Prop20100731");
- HANDLE g_hValue = (HANDLE)1;
- BOOL CALLBACK EnumWndProc(HWND hwnd,LPARAM lParam)
- {
-
HANDLE h = GetProp(hwnd, g_propName); - if(h == g_hValue)
-
{ -
*(HWND*)lParam = hwnd; -
return FALSE; -
} -
return TRUE; - }
- BOOL CXxxxDlg::OnInitDialog()
- {
-
CDialog::OnInitDialog(); -
//枚举窗口 -
HWND hOldWnd = NULL; -
EnumWindows(EnumWndProc, (LPARAM)&hOldWnd);//枚举所有运行的窗口 -
if(IsWindow(hOldWnd)) -
{ -
MessageBox(NULL, _T("应用程序已经在运行!"), _T("提示"), MB_ICONERROR|MB_OK); -
DestroyWindow(); -
return FALSE; -
} -
SetProp(m_hWnd, g_propName, g_hValue); - }
三、使用公共文件
四、mac地址验证
五、查看网络连接
- PMIB_TCPTABLE pTcpTable = new MIB_TCPTABLE[1];
- DWORD dwSize = 0;
- if(GetTcpTable(pTcpTable, &dwSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
- {
-
delete pTcpTable; -
pTcpTable = new MIB_TCPTABLE[dwSize / sizeof(MIB_TCPTABLE)]; - }
- if(GetTcpTable(pTcpTable, &dwSize, FALSE) == NO_ERROR)
- {
-
char cServerAddr[100];//服务器IP -
int nPort;//服务器端口号 -
DWORD dwIP = inet_addr(cServerAddr); -
DWORD dwPort = ((nPort & 0xff) << 8) + ((nPort & 0xff00) >> 8); -
for (int i = 0; i < (int) pTcpTable->dwNumEntries; i++) -
{ -
if(pTcpTable->table[i].dwRemoteAddr == dwIP -
&& pTcpTable->table[i].dwRemotePort == dwPort) -
{ -
MessageBox(gDataCenter.GetMainWnd(), _T("应用程序已经在运行!"), _T("提示"), MB_ICONERROR|MB_OK); -
return FALSE; -
} -
} - }
- delete []pTcpTable;
补充
windows系统下,程序防止多开的几种常见方法:
1)使用FindWindow API函数。
通过查找窗口标题(或/和类名)来判断程序是否正在运行。如果找到了,表明程序正在运行,这时可退出程序,达到不重复运行的效果;反之表明程序是第一次运行。
这种方法不适用于以下情况,程序的标题是动态变化的、系统中运行了相同标题(或/和类名)的程序
2)Mutex/Event/Semaphore
通过互斥对象/信号量/事件等线程同步对象来确定程序是否已经运行。最常用的函数如:CreateMutexA(注意:QQ堂、QQ游戏大厅就是采用这样方法来限制程序多开的)
3)内存映射文件(File Mapping)
通过把程序实例信息放到跨进程的内存映射文件中,也可以控制程序多开。
4)DLL全局共享区
DLL全局共享区在映射到各个进程的地址空间时仅被初始化一次,且是在第一次被windows加载时,所以利用该区数据就能对程序进行多开限制。
5)全局Atom
将某个特定字符串通过GlobalAddAtom加入全局原子表(Global Atom Table),程序运行时检查该串是否存在来限制程序多开。(该Atom不会自动释放,程序退出前必须调用GlobalDeleteAtom来释放Atom)
6)检查窗口属性
将某些数据通过SetProp加入到指定窗口的property list,程序运行时枚举窗口并检查这些数据是否存在来限制多开。
以上只列举了最常见的几种方法,具体应用中可以有n种选择,或综合运用多种方法来限制。