防止打开多个exe

lonelyrains 2010-11-19 03:44:14
编写了一个小应用程序,采用MFC工程,生成了exe文件。
代码中应添加什么内容,使得只允许打开一个exe例程。且在此点击该exe的图标时,已运行的该exe的实例放到桌面的顶端?
学MFC不久,请大家给些方法。方法越多越好!
...全文
928 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
MYNAMELIULI 2010-12-28
  • 打赏
  • 举报
回复
楼上的答得都不错.
chzhn 2010-12-28
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 freecodeman 的回复:]

问以上各楼,,如何 破解CreateMutex的方法,,,
使得可多开??
[/Quote]
如果在调试器里面调试的时候很简单,bp OpenMutexA(W),然后在返回的位置修改标志位达到跳转的目的,如果没有使用调试器,可以使用全局Hook IAT(导入表)的方法,修改OpenMutex函数结束的位置,比较当前进程名,如果是的话,修改标志位,然后返回。
青稞 2010-12-28
  • 打赏
  • 举报
回复
9楼的正解。。
创建互斥,然后判定该内核对象是否已经存在。。
如果已经存在,则Findwindow,把已经运行的窗口重新激活,显示在前面
//检测软件是否重复启动
BOOL ConsoleApp::IsRepeatRun()
{
BOOL bRet = FALSE;
m_hMutex = CreateMutex(NULL, FALSE, _T("AAAA"));
try
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(m_hMutex);
CWnd *pWndPrev = NULL;
CWnd *pWndChild = NULL;

pWndPrev = CWnd::FindWindow(NULL, _T("什么窗口"));
if (pWndPrev != NULL)
{
if (pWndPrev->IsIconic() == TRUE)
{
pWndPrev->ShowWindow(SW_RESTORE);
}
pWndChild = pWndPrev->GetLastActivePopup();
if (pWndChild != NULL)
{
pWndChild->SetForegroundWindow();
}
}
return TRUE;
}

}
catch (CException *e)
{
TCHAR szErr[255] = {0};
e->GetErrorMessage(szErr, 255);
MessageBox(NULL, szErr, _T("系统提示"), MB_OK | MB_ICONERROR);
return TRUE;
}

return bRet;
}
SiGoYi 2010-12-28
  • 打赏
  • 举报
回复

按上述做法如果程序非正常结束,不能把互斥对象释放是不是就会有问题。
个人感觉还是在每次启动时枚举一下进程名要好一些。
当然如果有人用黑客手段的话,那怎么也防不了。总有比你高的人。
chzhn 2010-12-28
  • 打赏
  • 举报
回复
还可以以独占文件的方法,感觉这个方法破解起来反而比较难,程序启动的时候以独占的方式打开一个特殊的重要文件(文件句柄直到程序退出才关闭),并使用该文件的数据,就像Windows的储巢文件一样。
jamseyang 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 coding_hello 的回复:]

CreateMutex啊,典型用法。命名对象前面加上Global\前缀,就可以全局唯一了。
不加前缀的话,换个桌面,比如远程桌面登录过来,就又能启动。
[/Quote]
现在才知道^_^
rolax 2010-12-22
  • 打赏
  • 举报
回复
创建互斥对象
wnx_u 2010-12-22
  • 打赏
  • 举报
回复
WinMain函数的第二个参数就是该程序的前一个进程句柄,第二个问题,只要发个消息把该窗口显示出来就可以了啊,很简单的啊
iamzxx 2010-12-21
  • 打赏
  • 举报
回复
CreateMutex啊,典型用法。命名对象前面加上Global\前缀,就可以全局唯一了。
不加前缀的话,换个桌面,比如远程桌面登录过来,就又能启动。

-------
谢谢了,我这阵正为这个烦恼呢!!
wangbo56916860 2010-12-20
  • 打赏
  • 举报
回复
命名空间 mutex 可能会导致DOS 得非法攻击
bulerain 2010-12-15
  • 打赏
  • 举报
回复
看看msdn的CreateMutex的说明:createfile然后lockfile,那么第一个进程creatfile的时候就不能lockfile了,这样来判断是否存在了一个实例。
mtj530 2010-12-15
  • 打赏
  • 举报
回复
楼上的答得都不错.
panasonic0804 2010-12-14
  • 打赏
  • 举报
回复
信号量的用法先学习了。
Simao 2010-12-14
  • 打赏
  • 举报
回复
学习学习了
xiaohuh421 2010-12-14
  • 打赏
  • 举报
回复
SEM_OBJECT TEXT("C_MAIN_OBJECT")

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam )
{
//TCHAR buf[100]={0};
//GetWindowText(hwnd,buf,100);
//OutputDebugString(buf);
if(::GetProp(hwnd,SEM_OBJECT))//遍历窗口,得到有SEM_OBJECT标记的窗口,
{
::ShowWindow(hwnd,SW_RESTORE);//显示这个窗口
::SetForegroundWindow(hwnd);//前台显示.
return FALSE;
}
return TRUE;
}



BOOL IsExeExist()
{
//让本程序只远行一个实例
//方法1
/*HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,TRUE,SEM_OBJECT);
if(NULL != hEvent)
{
//TCHAR buf[MAX_PATH]={0};
//GetModuleFileName(NULL,buf,MAX_PATH);
//CCheckObject ch;
//DWORD dwThreadId=ch.GetThreadId(PathFindFileName(buf));
//EnumThreadWindows(dwThreadId,EnumThreadWndProc,NULL);

CloseHandle(hEvent);
//OutputDebugString(TEXT("该程序已经在运行,不能打开另一个副本!"));
return TRUE;
}
m_hEvent = CreateEvent(NULL,TRUE,TRUE,SEM_OBJECT);*/

//方法2
HANDLE hSem=CreateSemaphore(NULL,1,1,SEM_OBJECT);//创建这个标记
if(hSem)
{
if(ERROR_ALREADY_EXISTS==GetLastError())//如果是已经存在,则说明程序已经运行过.
{
EnumWindows(EnumWindowsProc,NULL);//枚举哪个窗口有这个标记
return TRUE;
}
}

return FALSE;
}

BOOL chSetProp(HWND hWnd)
{
if(hWnd)
{
if(::SetProp(hWnd,SEM_OBJECT,(HANDLE)112233))//设置某个窗口拥有这个标记,
{ //第三个参数可以不管.
m_hWnd=hWnd;
return TRUE;
}
}
return FALSE;
}

调用方法:
if(IsExist()==FALSE)//是否存在
{
chSetProp(hWnd);不存在则把当前窗口设置拥有这个标记.
}
sd666850 2010-12-14
  • 打赏
  • 举报
回复
方法很多啊,CreateSemaphore我就知道这一个
xuting0 2010-12-14
  • 打赏
  • 举报
回复
CreatMutex()创建命名对象
if(ERROR_ALREADY_EXISTS == GetLastError())
{
AfxMessageBox("已经运行");
return;
}
Lingxy 2010-12-10
  • 打赏
  • 举报
回复
////////// 该方法运行一个实例并激活该程序
// 用应用程序名创建信号量
HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszExeName);

// 信号量已存在? 信号量存在,则程序已有一个实例运行
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// 关闭信号量句柄
CloseHandle(hSem);

// 寻找先前实例的主窗口
HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (::IsWindow(hWndPrevious))
{
// 检查窗口是否有预设的标记? 有,则是我们寻找的主窗
if (::GetProp(hWndPrevious, m_pszExeName))
{
//::SendMessage(hWndPrevious,::RegisterWindowMessage(_T("RestoreWindow")),0,0);
// 主窗口已最小化,则恢复其大小
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious, SW_RESTORE);
// 将主窗激活
::SetForegroundWindow(hWndPrevious);

// 退出本实例
return FALSE;
}//if (::GetProp(hWndPrevious, m_pszExeName)){

// 继续寻找下一个窗口
hWndPrevious = ::GetWindow(hWndPrevious, GW_HWNDNEXT);
}//while (::IsWindow(hWndPrevious)){

// 若运行到此,说明没有执行 While 中的 return FALSE,即:
// 前一实例已存在,但找不到其主窗。 可能出错了
return FALSE; // 退出本实例
}//if (GetLastError() == ERROR_ALREADY_EXISTS)
//////////////////////////////end
cmlr_ 2010-12-02
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 coding_hello 的回复:]

CreateMutex啊,典型用法。命名对象前面加上Global\前缀,就可以全局唯一了。
不加前缀的话,换个桌面,比如远程桌面登录过来,就又能启动。
[/Quote]

啊,还有这一说,不错,学习了
野男孩 2010-12-01
  • 打赏
  • 举报
回复
CreateMutex啊,典型用法。命名对象前面加上Global\前缀,就可以全局唯一了。
不加前缀的话,换个桌面,比如远程桌面登录过来,就又能启动。
加载更多回复(23)

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧