让程序只运行一个实例
来源:百度文库 编辑:神马文学网 时间:2024/04/28 17:54:57
在我们的程序当中如果要实现只运行一个实例的功能,就要解决两个问题,首先是要判断该程序已有一个实例在运行,其次是要将已运行的应用程序实例激活,同时退出第二个应用程序实例。对于第一个问题,我们可以通过设置命名互斥对象或命名信标对象,在程序启动的时候检测互斥对象或信标对象,如互斥对象或信标对象已存在,则可以判断此程序已有一个实例正在运行。第二个问题是如何找到已经运行的应用程序实例,如果我们能够找到已运行实例主窗口的指针,即可调用SetForegroundWindow来激活该实例。我们可以通过两种形式找到已运行实例的主窗口,一种形式是通过调用FindWindowEx去查找正在运行的窗口的句柄,这种方式用得比较多一些,而本文通过另一种形式去查找正在运行的窗口的句柄。通过调用SetProp给应用程序主窗口设置一个标记,用GetDesktopWindow可以获取Windows环境下的桌面窗口的句柄,所有应用程序的主窗口都可以看成该窗口的子窗口,接着我们就可以用GetWindow函数来获得这些窗口的句柄。然后再用Win32SDK函数GetProp查找每一个应用程序的主窗口是否包含有我们设置的标记,这样就可以找到我们要找的第一个实例主窗口。 1、在应用程序类InitInstance()函数中判断是否已有一个应用程序实例正在运行。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_pszExeName))
{
// 主窗口已最小化,则恢复其大小
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious,SW_RESTORE);
// 将主窗激活
::SetForegroundWindow(hWndPrevious);
// 将主窗的对话框激活
::SetForegroundWindow(
::GetLastActivePopup(hWndPrevious));
// 退出本实例
return FALSE;
}
// 继续寻找下一个窗口
hWndPrevious = ::GetWindow(hWndPrevious,GW_HWNDNEXT);
}
// 前一实例已存在,但找不到其主窗
// 可能出错了
// 退出本实例
return FALSE;
} ......} 2、在框架类的OnCreate()函数中设置查找标记。int CEllipseWndDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
// 设置寻找标记
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
return 0;
}
3、在程序退出是删除设置的标记,在框架类中响应WM_DESTROY消息,进行处理。void CEllipseWndDlg::OnDestroy()
{
CDialog::OnDestroy();
// 删除寻找标记
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
} 查看代码和VC的帮助后,发现问题在于原文在创建信号量和设置寻找标记时使用的是 CWinApp 的成员变量m_pszExeName,该成员变量其实是应用程序执行文件的名称去掉扩展名后的部分,而不是应用程序名。真正的应用程序名应为成员变量 m_pszAppName, 于是将用到m_pszExeName的三处代码均改为m_pszAppName,重新编译执行,情况消失。
最后再提供一个方法和一个信息:
另一种使应用程序只能运行一个实例的方法,只需在InitInstance()的最开始添
加下列语句即可:
HANDLE m_hMutex=CreateMutex(NULL,TRUE, m_pszAppName);
if(GetLastError()==ERROR_ALREADY_EXISTS) { return FALSE; }
但这种方法的不足之处是不能将已经启动的实例激活。
{
// 用应用程序名创建信号量
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))
{
// 主窗口已最小化,则恢复其大小
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious,SW_RESTORE);
// 将主窗激活
::SetForegroundWindow(hWndPrevious);
// 将主窗的对话框激活
::SetForegroundWindow(
::GetLastActivePopup(hWndPrevious));
// 退出本实例
return FALSE;
}
// 继续寻找下一个窗口
hWndPrevious = ::GetWindow(hWndPrevious,GW_HWNDNEXT);
}
// 前一实例已存在,但找不到其主窗
// 可能出错了
// 退出本实例
return FALSE;
} ......} 2、在框架类的OnCreate()函数中设置查找标记。int CEllipseWndDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
// 设置寻找标记
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
return 0;
}
3、在程序退出是删除设置的标记,在框架类中响应WM_DESTROY消息,进行处理。void CEllipseWndDlg::OnDestroy()
{
CDialog::OnDestroy();
// 删除寻找标记
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
} 查看代码和VC的帮助后,发现问题在于原文在创建信号量和设置寻找标记时使用的是 CWinApp 的成员变量m_pszExeName,该成员变量其实是应用程序执行文件的名称去掉扩展名后的部分,而不是应用程序名。真正的应用程序名应为成员变量 m_pszAppName, 于是将用到m_pszExeName的三处代码均改为m_pszAppName,重新编译执行,情况消失。
最后再提供一个方法和一个信息:
另一种使应用程序只能运行一个实例的方法,只需在InitInstance()的最开始添
加下列语句即可:
HANDLE m_hMutex=CreateMutex(NULL,TRUE, m_pszAppName);
if(GetLastError()==ERROR_ALREADY_EXISTS) { return FALSE; }
但这种方法的不足之处是不能将已经启动的实例激活。
让程序只运行一个实例
运行程序
新手功略(如何运行好一个HelloWorld程序)
新手功略(如何运行好一个HelloWorld程序)
新手功略(如何运行好一个HelloWorld程序)
从命令着手 让Windows程序运行简单快捷(2)
让ASP程序运行于非Windows平台
让.Net程序脱离.net framework框架运行
VB开机运行程序
怎样限制程序运行
程序运行计时技巧
Shell程序实例集锦一
让SQL程序更快的运行:语句优化分析(2)
如何在用户中止了浏览器之后,让php程序继续运行?
让.Net程序脱离.net framework框架运行的方法(转载) - kingeric的空间 - 博客园
编程入门网-如何锁定一些我不想让别人运行的程序
从命令着手 让Windows程序运行简单快捷(2) - ZDNet China软件技术专区
成都公示“权力运行程序”
C 程序开发经典实例之一 - 软件屋
使用thinkPHP做注册程序的实例
C 程序开发经典实例之一 - 软件屋
进程、窗口句柄、文件属性、程序运行状态
进程、窗口句柄、文件属性、程序运行状态
办公室主要行政业务运行程序