- 浏览: 14979 次
最新评论
使应用程序只能运行一个实例
2010年07月16日
这里涉及两个基本的问题,一是在程序的第二个实例启动时,如何发现该程序已有
一个实例在运行,而是如何将第一个实例激活,而第二个实例退出。
方法一:
对于第一个问题,可以通过给应用程序设置信号量,实例启动时首先检测该信号量,
如已存在,则说明程序已运行一个实例。
第二个问题的难点是获取第一个实例的主窗对象指针或句柄,然后便可用
SetForegroundWindow来激活。虽然FindWindow函数能寻找正运行着的窗口,但该函
数要求指明所寻找窗口的标题或窗口类名,不是实现通用方法的途径。
我们可以用Win32 SDK函数SetProp来给应用程序主窗设置一个特有的标记。
用GetDesktopWindow 可以获取Windows系统主控窗口对象指针或句柄,所有应用程
序主窗都可看成该窗口的子窗口,即可用GetWindow函数来获得它们的对象指针或句
柄。用Win32 SDK函数GetProp查找每一应用程序主窗是否包含有我们设置的特定标
记便可确定它是否我们要寻找的第一个实例主窗。使第二个实例退出很简单,只要
让其应用程序对象的InitInstance函数返回FALSE即可。此外,当主窗口退出时,应
用RemoveProp函数删除我们为其设置的标记。
下面的InitInstance、OnCreate和OnDestroy函数代码将实现上述的操作:
BOOL CEllipseWndApp::InitInstance()
{
// 用应用程序名创建信号量
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_pszAppName))
{
// 主窗口已最小化,则恢复其大小 这里针对最小化的情况,如果不是最小化,则取消if判断
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious,SW_RESTORE);
// 将主窗激活
::SetForegroundWindow(hWndPrevious);
// 将主窗的对话框激活
::SetForegroundWindow(
::GetLastActivePopup(hWndPrevious));
// 退出本实例
return FALSE;
}
// 继续寻找下一个窗口
hWndPrevious = ::GetWindow(hWndPrevious,GW_HWNDNEXT);
}
// 前一实例已存在,但找不到其主窗
// 可能出错了
// 退出本实例
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic();// Call this when linking to MFC statically
#endif
CEllipseWndDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
int CEllipseWndDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
// 设置寻找标记
::SetProp(m_hWnd, AfxGetApp()->m_pszAppName, (HANDLE)1);
return 0;
}
void CEllipseWndDlg::OnDestroy()
{
CDialog::OnDestroy();
// 删除寻找标记
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
}
方法二:
使用互斥器CMutex
缺点:
当用户已TS的方式登陆的时候,他们是可以打开两个实例,即方法一和方法二无效。
解决方案:
方法三:锁定文件
// 程序只能运行一次
m_hLockFile = CreateFile(_T("lockfile.sys"), GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( INVALID_HANDLE_VALUE == m_hLockFile)
{
AfxMessageBox(_T("程序不能重复打开!"));
return FALSE;
}
方法四:巧用程序共享区域
1.设定共享变量
#pragma data_seg("share_data")
int _app_count_ = 0;
#pragma data_seg()
#pragma comment(linker, "/section:share_data,RWS")
2. 在Instance函数中写入如下代码
if(_app_count_ > 0) return FAlSE; // 已经有实例在运行
else _app_count_++;
发表评论
-
[原创]Google App Engine使用简介
2012-01-20 02:06 1030[原创]Google App Engine使用 ... -
异常处理
2012-01-20 02:06 701异常处理 2010年07月23日 下面的代码举例说明了一 ... -
Android:Debug certificate expired on DATE 解决方法
2012-01-20 02:06 896Android:Debug certificate expir ... -
诺基亚手机里的秘密
2012-01-19 09:56 584诺基亚手机里的秘密 2011年05月18日 诺基亚手机* ... -
Windows XP系统文件一一诠释(1)[最新整理](转BY wang6610----BBS.WUYOU.COM)
2012-01-19 09:56 781Windows XP系统文件一一诠 ... -
5230
2012-01-19 09:56 5585230 2010年12月31日 一、购机后的头两件 ... -
sdsadsadas
2012-01-19 09:56 556sdsadsadas 2010年11月22日 XV67 ... -
5230
2012-01-19 09:56 6205230 2010年10月03日 1、屏幕保护:一定要买 ... -
ReleaseDC和DeleteDC的区别 (转)
2012-01-17 02:27 884ReleaseDC和DeleteDC的区别 (转) 2011 ... -
FlashBuilder4.5 下载 及破解方法
2012-01-17 02:27 717FlashBuilder4.5 下载 及破解方法 2011年 ... -
ROOT【个人学习,慎用】
2012-01-17 02:27 633ROOT【个人学习,慎用】 ... -
(转) iPhone UI 开发的几点建议
2012-01-17 02:27 531(转) iPhone UI 开发的几点 ... -
MFC自定义消息
2012-01-17 02:26 625MFC自定义消息 2011年11月28日 MFC自定义消 ... -
workplan
2012-01-15 22:12 405workplan 2011年04月18日 ... -
.net自定义控件小结进阶篇
2012-01-15 22:12 853.net自定义控件小结进阶篇 2010年12月14日 ... -
WPF中的控件
2012-01-15 22:12 1206WPF中的控件 2011年05月17日 1.Button ... -
【C#】在VS2005中C#实现鼠标悬停提示
2012-01-15 22:12 1475【C#】在VS2005中C#实现鼠标悬停提示 2010年01 ... -
flex ComboBox显示的字太长,用......代替
2012-01-15 22:12 1057flex ComboBox显示的字太长,用......代替 ...
相关推荐
如何使应用程序只运行一个实例(11kb)
转自 :如何使应用程序只运行一个实例 VC ,
该文档详细描述了QT平台下,让应用程序只运行一个实例的三种方法,并附有相应的代码。
Delphi中防止运行一个应用程序的多个实例2个办法 弹出提醒 激活窗口 Delphi源代码3份。
c#应用程序如何只运行一个实例
如何使一个应用的多个实例运行在同一个进程空间
当应用程序已经在运行, 再次运行该应用程序时,通常只是把该应用程序的窗口提到前面来,把新的命令行参数传递给第一个运行实例,而第二个实例退出。这在传统的单进程多线程的手机 平台中,实现是简单而直接的,而在...
c++ vs2008 应用程序只有一个实例 简单的demo 启动程序
MFC编写的控制MFC程序,判断只能运行一次,编译成功,能够直接用
保证应用程序只有一个实例运行! 很值得下载看看!资源免费,大家分享!!
使用共享内存和信号量实现QT应用程序单实例的方法,并且支持根据需要弹出已经运行的程序窗口,解决了同类软件存在的问题,而且程序非常简单。
在我们的程序当中如果要实现类似《360软件管家》的功能,就要解决两个问题,首先是要判断该程序已有一个实例在运行,其次是要将已运行的应用程序实例激活,同时退出第二个应用程序实例。 对于第一个问题,我们可以...
摘要:VC/C++源码,界面编程,应用程序 VC++将应用程序已运行的实例调至前台,源码运行截图如上所示。
vc++程序源代码,如何将应用程序已运行的实例调至前台
项目9 应用程序设计实例 任务2 系统设计 【例1】根据应用程序设计系统分析,创建一个项目文件"产品管理.pjx"。 1.设计数据库和表 2.设计启动界面 3.设计登录界面 4.设计系统菜单 5.表单设计 6.报表设计 7....
是一个可以运行的JAVA应用程序 具有界面 有详细注解
用C#给程序加启动画面并只允许一个应用程序实例运行[借鉴].pdf
可以使用互斥体Mutex类型完成此功能。见如下代码: [STAThread]c_让应用程序只有一个实例运行
C#语言Winform应用程序判定是否已运行实例,采用互斥锁
一个顺序控制,急停保持当前步,复位后继续当前步运行的程序.zip三菱PLC编程案例源码资料编程控制器应用通讯通信例子程序实例一个顺序控制,急停保持当前步,复位后继续当前步运行的程序.zip三菱PLC编程案例源码资料...