我想,把大家的方法都贴出来吧!OPEN 一把!
16 个解决方案
#1
关注:O===O
#2
(转的,呵呵)
用互斥(Mutex),Mutex本来是多线程同步用的,防止
多个线程访问同一资源而引发冲突。用CreateMutex可以
创建Mutex对象,实质上是一个kernel对象。
在任何Win32程序(包括GDI和Console)的启动部分加上
以下代码(Console程序的main函数、MFC程序的CWinApp
派生类的InitInstance成员函数、RawSDK程序的WinMain
函数):
hMutex=CreateMutex(
NULL,//nosecurityattributes
FALSE,//initiallynotowned
"RunOnlyOneInstance");//命名Mutex是全局对象
//在所有的process都可以访问到
if(hMutex==NULL||
ERROR_ALREADY_EXISTS==::GetLastError()){
//程序第二次或以后运行时,会得到Mutex已经创建的错误
returnFALSE;
}
嘿嘿,是不是不用FindWindow优雅简洁多了?
另外,如果要限定程序同时可运行n个实例怎么办?
Tips:用信号量(Semaphore)。
用互斥(Mutex),Mutex本来是多线程同步用的,防止
多个线程访问同一资源而引发冲突。用CreateMutex可以
创建Mutex对象,实质上是一个kernel对象。
在任何Win32程序(包括GDI和Console)的启动部分加上
以下代码(Console程序的main函数、MFC程序的CWinApp
派生类的InitInstance成员函数、RawSDK程序的WinMain
函数):
hMutex=CreateMutex(
NULL,//nosecurityattributes
FALSE,//initiallynotowned
"RunOnlyOneInstance");//命名Mutex是全局对象
//在所有的process都可以访问到
if(hMutex==NULL||
ERROR_ALREADY_EXISTS==::GetLastError()){
//程序第二次或以后运行时,会得到Mutex已经创建的错误
returnFALSE;
}
嘿嘿,是不是不用FindWindow优雅简洁多了?
另外,如果要限定程序同时可运行n个实例怎么办?
Tips:用信号量(Semaphore)。
#3
很容易的,查找第一个窗口,然后激活以前的。
HWND hOldInstance;
if((hOldInstance=::FindWindow(NULL,_T("志软个人信息管理")))!=NULL)
{
ShowWindow(hOldInstance,SW_RESTORE|SW_SHOWNORMAL);
SetForegroundWindow(hOldInstance);
return FALSE;
}
HWND hOldInstance;
if((hOldInstance=::FindWindow(NULL,_T("志软个人信息管理")))!=NULL)
{
ShowWindow(hOldInstance,SW_RESTORE|SW_SHOWNORMAL);
SetForegroundWindow(hOldInstance);
return FALSE;
}
#4
我的方法和bodies一样,但就是不知道怎么激活以前的窗口。
#5
转贴的哦:
#define INSTANCEMAINWNDPROP _T("your special string")
BOOL CYourApp::InitInstance()
{
if(CheckSingleInstance()==FALSE)
{
return FALSE; //则程序安全退出
}
//......
}
BOOL CYourApp::CheckSingleInstance()
{
::CreateMutex(NULL,TRUE,INSTANCEMAINWNDPROP);
if(::GetLastError()==ERROR_ALREADY_EXISTS)
{
//set focus to previous instance
CWnd* pPrevWnd=CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);
while(pPrevWnd)
{
if(::GetProp(pPrevWnd->GetSafeHwnd(),INSTANCEMAINWNDPROP))
{
if(pPrevWnd->IsIconic())
{
pPrevWnd->ShowWindow(SW_RESTORE);
}
pPrevWnd->SetForegroundWindow();
pPrevWnd->GetLastActivePopup()->SetForegroundWindow();
break;
}
pPrevWnd=pPrevWnd->GetWindow(GW_HWNDNEXT);
}
return FALSE;
}
return TRUE;
}
int CYourMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
::SetProp(GetSafeHwnd(),INSTANCEMAINWNDPROP,(HANDLE)1);
//......
}
void CYourMainWnd::OnDestroy()
{
::RemoveProp(GetSafeHwnd(),INSTANCEMAINWNDPROP);
CWnd::OnDestroy();
}
http://www.csdn.net/expert/topic/78/78172.shtm
在这里啦
#define INSTANCEMAINWNDPROP _T("your special string")
BOOL CYourApp::InitInstance()
{
if(CheckSingleInstance()==FALSE)
{
return FALSE; //则程序安全退出
}
//......
}
BOOL CYourApp::CheckSingleInstance()
{
::CreateMutex(NULL,TRUE,INSTANCEMAINWNDPROP);
if(::GetLastError()==ERROR_ALREADY_EXISTS)
{
//set focus to previous instance
CWnd* pPrevWnd=CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);
while(pPrevWnd)
{
if(::GetProp(pPrevWnd->GetSafeHwnd(),INSTANCEMAINWNDPROP))
{
if(pPrevWnd->IsIconic())
{
pPrevWnd->ShowWindow(SW_RESTORE);
}
pPrevWnd->SetForegroundWindow();
pPrevWnd->GetLastActivePopup()->SetForegroundWindow();
break;
}
pPrevWnd=pPrevWnd->GetWindow(GW_HWNDNEXT);
}
return FALSE;
}
return TRUE;
}
int CYourMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
::SetProp(GetSafeHwnd(),INSTANCEMAINWNDPROP,(HANDLE)1);
//......
}
void CYourMainWnd::OnDestroy()
{
::RemoveProp(GetSafeHwnd(),INSTANCEMAINWNDPROP);
CWnd::OnDestroy();
}
http://www.csdn.net/expert/topic/78/78172.shtm
在这里啦
#6
我是这样做的,不过不是最好的办法
BOOL CThread01App::InitInstance()
{
CMutex vMutex(FALSE,MUTEXNAME,NULL);
BOOL bResult;
HWND vShowWindow;
DWORD err;
bResult = vMutex.Lock(0); //判断实例是否已经启动
if (!bResult)
{
//是,则显示实例
vShowWindow = ::FindWindow(LPCTSTR("#32770"),LPCTSTR("Thread01"));
if (vShowWindow == NULL)
{
err = GetLastError();
exit(0);
}
::ShowWindow((HWND)vShowWindow,SW_SHOWNORMAL); //设置窗口属性
::SetForegroundWindow((HWND)vShowWindow); //设置窗口在最前面
exit(0);
}
...
}
在显示该实例的处理上不是很好,不知道有什么更好的方法,请指教!
BOOL CThread01App::InitInstance()
{
CMutex vMutex(FALSE,MUTEXNAME,NULL);
BOOL bResult;
HWND vShowWindow;
DWORD err;
bResult = vMutex.Lock(0); //判断实例是否已经启动
if (!bResult)
{
//是,则显示实例
vShowWindow = ::FindWindow(LPCTSTR("#32770"),LPCTSTR("Thread01"));
if (vShowWindow == NULL)
{
err = GetLastError();
exit(0);
}
::ShowWindow((HWND)vShowWindow,SW_SHOWNORMAL); //设置窗口属性
::SetForegroundWindow((HWND)vShowWindow); //设置窗口在最前面
exit(0);
}
...
}
在显示该实例的处理上不是很好,不知道有什么更好的方法,请指教!
#7
Q243953 HOWTO: Limit 32-bit Applications to One Instance Using C++
#8
利用注册表、互斥对象、原子、FindWindow、都可以!
#9
继续?
#10
关注!
#11
继续?
#12
贴上我的笔记:
方案一: 查找窗口类
方案二: 设置窗口属性
方案三: 使用文件映像
方案四: 使用原子
方案五: 使用同步对象
方案一: 使用注册类查找的方法实现单实例运行
例:
①C???App::InitInstance
BOOL C???App::InitInstance()
{
if (!FirstInstance())
return FALSE;
beRegisted=TRUE;
m_pMainWnd =new CMainWnd();
m_pMainWnd->CreateEx(0,"fmdmainwnd",
_T("CodeHelper"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
其中beRegisted为C???App成员
public:
BOOL beRegisted;
②C???App::FirstInstance
BOOL CMainApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd;
if (PrevCWnd = CWnd::FindWindow("fmdmainwnd",NULL))
{
ChildCWnd=PrevCWnd->GetLastActivePopup();
PrevCWnd->BringWindowToTop();
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE);
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop();
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}
③C???App::InitApplication
BOOL CMainApp::InitApplication()
{
CWinApp::InitApplication();
WNDCLASS wndcls;
//注册自定义类
memset(&wndcls, 0, sizeof(WNDCLASS));
//窗口基本类型
wndcls.style=CS_DBLCLKS ¦ CS_HREDRAW ¦ CS_VREDRAW;
wndcls.lpfnWndProc=::DefWindowProc;
wndcls.hInstance=AfxGetInstanceHandle();
wndcls.hIcon=LoadIcon(IDR_MAIN);
wndcls.hCursor=LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndcls.lpszMenuName=MAKEINTRESOURCE(IDR_MAIN);
wndcls.lpszClassName="fmdmainwnd";
return AfxRegisterClass(&wndcls);
}
④C???App::ExitInstance
int CMainApp::ExitInstance()
{
if(beRegisted)
::UnregisterClass("fmdmainwnd", AfxGetInstanceHandle());
return CWinApp::ExitInstance();
}
方案二:设置窗口附加属性 int C???Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
......
}
void C???Dlg::OnDestroy()
{
......
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
......
}
BOOL CEllipseWndApp::InitInstance()
{
// Create a Semaphore with a name of application exename
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;
}
C????Dlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
}
return FALSE;
}
方案三:使用文件映像
另文有述
方案四:使用原子
BOOL C???App::InitInstance()
{
.....
if(GlobalFindAtom("AdBreaker")) //找原子
return false;
ATOM GlobalAtom=GlobalAddAtom("AdBreaker"); //添加原子
CAdBreakerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
.....
GlobalDeleteAtom(GlobalAtom);
return FALSE;
}
方案五:使用同步对象 InitInstance中
HANDLE m_hMutex =
CreateMutex(NULL,TRUE,m_pszAppName);
if (GetLastError()==ERROR_ALREADY_EXISTS){
return FALSE;
}
另:在
http://www.csdn.net/expert/topic/159/159112.shtm
中liuqiannan(二迷糊) 的方案也不错:
回复人:liuqiannan(二迷糊) (2001-6-14 22:28:00) 得0分
用一个共享数据段,定义一个用来计数的长整形
#pragma data_seg(".OnlyOne")
long 1Count=-1;
#pragma data_seg()
用DEF文件定义共享属性
SECTIONS
.OnlyOne READ WRITE SHARED
在初始化阶段,如InitInstance开始处,加入
BOOL bFirstInit=(InterlockedIncrement($1InstanceCount)==0)
if(!bFirstInit)
{
AfxMessageBox("该程序已经运行",MB_OK¦MB_ICONSTOP);
InterlockedDecrement($1InstanceCount);
return FALSE;
}
程序结束后,调用:
InterlockedDecrement(&1InstanceCount);
综合,以上朋友的发言,应该有不少了,但只有少数能作到,将前一个实例激活
方案一: 查找窗口类
方案二: 设置窗口属性
方案三: 使用文件映像
方案四: 使用原子
方案五: 使用同步对象
方案一: 使用注册类查找的方法实现单实例运行
例:
①C???App::InitInstance
BOOL C???App::InitInstance()
{
if (!FirstInstance())
return FALSE;
beRegisted=TRUE;
m_pMainWnd =new CMainWnd();
m_pMainWnd->CreateEx(0,"fmdmainwnd",
_T("CodeHelper"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
其中beRegisted为C???App成员
public:
BOOL beRegisted;
②C???App::FirstInstance
BOOL CMainApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd;
if (PrevCWnd = CWnd::FindWindow("fmdmainwnd",NULL))
{
ChildCWnd=PrevCWnd->GetLastActivePopup();
PrevCWnd->BringWindowToTop();
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE);
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop();
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}
③C???App::InitApplication
BOOL CMainApp::InitApplication()
{
CWinApp::InitApplication();
WNDCLASS wndcls;
//注册自定义类
memset(&wndcls, 0, sizeof(WNDCLASS));
//窗口基本类型
wndcls.style=CS_DBLCLKS ¦ CS_HREDRAW ¦ CS_VREDRAW;
wndcls.lpfnWndProc=::DefWindowProc;
wndcls.hInstance=AfxGetInstanceHandle();
wndcls.hIcon=LoadIcon(IDR_MAIN);
wndcls.hCursor=LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndcls.lpszMenuName=MAKEINTRESOURCE(IDR_MAIN);
wndcls.lpszClassName="fmdmainwnd";
return AfxRegisterClass(&wndcls);
}
④C???App::ExitInstance
int CMainApp::ExitInstance()
{
if(beRegisted)
::UnregisterClass("fmdmainwnd", AfxGetInstanceHandle());
return CWinApp::ExitInstance();
}
方案二:设置窗口附加属性 int C???Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
......
}
void C???Dlg::OnDestroy()
{
......
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
......
}
BOOL CEllipseWndApp::InitInstance()
{
// Create a Semaphore with a name of application exename
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;
}
C????Dlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
}
return FALSE;
}
方案三:使用文件映像
另文有述
方案四:使用原子
BOOL C???App::InitInstance()
{
.....
if(GlobalFindAtom("AdBreaker")) //找原子
return false;
ATOM GlobalAtom=GlobalAddAtom("AdBreaker"); //添加原子
CAdBreakerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
.....
GlobalDeleteAtom(GlobalAtom);
return FALSE;
}
方案五:使用同步对象 InitInstance中
HANDLE m_hMutex =
CreateMutex(NULL,TRUE,m_pszAppName);
if (GetLastError()==ERROR_ALREADY_EXISTS){
return FALSE;
}
另:在
http://www.csdn.net/expert/topic/159/159112.shtm
中liuqiannan(二迷糊) 的方案也不错:
回复人:liuqiannan(二迷糊) (2001-6-14 22:28:00) 得0分
用一个共享数据段,定义一个用来计数的长整形
#pragma data_seg(".OnlyOne")
long 1Count=-1;
#pragma data_seg()
用DEF文件定义共享属性
SECTIONS
.OnlyOne READ WRITE SHARED
在初始化阶段,如InitInstance开始处,加入
BOOL bFirstInit=(InterlockedIncrement($1InstanceCount)==0)
if(!bFirstInit)
{
AfxMessageBox("该程序已经运行",MB_OK¦MB_ICONSTOP);
InterlockedDecrement($1InstanceCount);
return FALSE;
}
程序结束后,调用:
InterlockedDecrement(&1InstanceCount);
综合,以上朋友的发言,应该有不少了,但只有少数能作到,将前一个实例激活
#13
用GUID做命名内核对象的名字,这样比较好
#14
呀,来晚了,那再说一种吧,
可以用内存映射文件实现:
MutexRuning为程序名
初始化阶段:
InitInstance中:
HANDLE hMap=CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,128,
"MutexRuning");
if(hMap==NULL)
{
AfxMessageBox("创建内存映射文件失败",MB_OK|MB_ICONSTOP);
return FALSE;
}
else if(GetLasError()==ERROR_ALREADY_EXISTS)
{
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
CString str=(char *)lpMem;
UnmapViewOfile(lpMem);
CloseHandle(hMap);
AfxMessageBox(str,MB_OK|MB_ICONSTOP);
return FALSE;
}
else
{
//是第一次运行
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
//程序运行描述信息
strcpy((char *) lpMem,"xxxx正在运行!");
UnmapViewOfFile(lpMem);
}
可以用内存映射文件实现:
MutexRuning为程序名
初始化阶段:
InitInstance中:
HANDLE hMap=CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,128,
"MutexRuning");
if(hMap==NULL)
{
AfxMessageBox("创建内存映射文件失败",MB_OK|MB_ICONSTOP);
return FALSE;
}
else if(GetLasError()==ERROR_ALREADY_EXISTS)
{
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
CString str=(char *)lpMem;
UnmapViewOfile(lpMem);
CloseHandle(hMap);
AfxMessageBox(str,MB_OK|MB_ICONSTOP);
return FALSE;
}
else
{
//是第一次运行
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
//程序运行描述信息
strcpy((char *) lpMem,"xxxx正在运行!");
UnmapViewOfFile(lpMem);
}
#15
Mutex可以做互斥,看看操作系统的书吧
#16
BOOL CXXXApp::InitInstance()
{
...
HANDLE m_hMutex=CreateMutex(NULL,TRUE, m_pszAppName);
if(GetLastError()==ERROR_ALREADY_EXISTS) {
AfxMessageBox("已经运行!");
return FALSE; }
...
}
{
...
HANDLE m_hMutex=CreateMutex(NULL,TRUE, m_pszAppName);
if(GetLastError()==ERROR_ALREADY_EXISTS) {
AfxMessageBox("已经运行!");
return FALSE; }
...
}
#1
关注:O===O
#2
(转的,呵呵)
用互斥(Mutex),Mutex本来是多线程同步用的,防止
多个线程访问同一资源而引发冲突。用CreateMutex可以
创建Mutex对象,实质上是一个kernel对象。
在任何Win32程序(包括GDI和Console)的启动部分加上
以下代码(Console程序的main函数、MFC程序的CWinApp
派生类的InitInstance成员函数、RawSDK程序的WinMain
函数):
hMutex=CreateMutex(
NULL,//nosecurityattributes
FALSE,//initiallynotowned
"RunOnlyOneInstance");//命名Mutex是全局对象
//在所有的process都可以访问到
if(hMutex==NULL||
ERROR_ALREADY_EXISTS==::GetLastError()){
//程序第二次或以后运行时,会得到Mutex已经创建的错误
returnFALSE;
}
嘿嘿,是不是不用FindWindow优雅简洁多了?
另外,如果要限定程序同时可运行n个实例怎么办?
Tips:用信号量(Semaphore)。
用互斥(Mutex),Mutex本来是多线程同步用的,防止
多个线程访问同一资源而引发冲突。用CreateMutex可以
创建Mutex对象,实质上是一个kernel对象。
在任何Win32程序(包括GDI和Console)的启动部分加上
以下代码(Console程序的main函数、MFC程序的CWinApp
派生类的InitInstance成员函数、RawSDK程序的WinMain
函数):
hMutex=CreateMutex(
NULL,//nosecurityattributes
FALSE,//initiallynotowned
"RunOnlyOneInstance");//命名Mutex是全局对象
//在所有的process都可以访问到
if(hMutex==NULL||
ERROR_ALREADY_EXISTS==::GetLastError()){
//程序第二次或以后运行时,会得到Mutex已经创建的错误
returnFALSE;
}
嘿嘿,是不是不用FindWindow优雅简洁多了?
另外,如果要限定程序同时可运行n个实例怎么办?
Tips:用信号量(Semaphore)。
#3
很容易的,查找第一个窗口,然后激活以前的。
HWND hOldInstance;
if((hOldInstance=::FindWindow(NULL,_T("志软个人信息管理")))!=NULL)
{
ShowWindow(hOldInstance,SW_RESTORE|SW_SHOWNORMAL);
SetForegroundWindow(hOldInstance);
return FALSE;
}
HWND hOldInstance;
if((hOldInstance=::FindWindow(NULL,_T("志软个人信息管理")))!=NULL)
{
ShowWindow(hOldInstance,SW_RESTORE|SW_SHOWNORMAL);
SetForegroundWindow(hOldInstance);
return FALSE;
}
#4
我的方法和bodies一样,但就是不知道怎么激活以前的窗口。
#5
转贴的哦:
#define INSTANCEMAINWNDPROP _T("your special string")
BOOL CYourApp::InitInstance()
{
if(CheckSingleInstance()==FALSE)
{
return FALSE; //则程序安全退出
}
//......
}
BOOL CYourApp::CheckSingleInstance()
{
::CreateMutex(NULL,TRUE,INSTANCEMAINWNDPROP);
if(::GetLastError()==ERROR_ALREADY_EXISTS)
{
//set focus to previous instance
CWnd* pPrevWnd=CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);
while(pPrevWnd)
{
if(::GetProp(pPrevWnd->GetSafeHwnd(),INSTANCEMAINWNDPROP))
{
if(pPrevWnd->IsIconic())
{
pPrevWnd->ShowWindow(SW_RESTORE);
}
pPrevWnd->SetForegroundWindow();
pPrevWnd->GetLastActivePopup()->SetForegroundWindow();
break;
}
pPrevWnd=pPrevWnd->GetWindow(GW_HWNDNEXT);
}
return FALSE;
}
return TRUE;
}
int CYourMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
::SetProp(GetSafeHwnd(),INSTANCEMAINWNDPROP,(HANDLE)1);
//......
}
void CYourMainWnd::OnDestroy()
{
::RemoveProp(GetSafeHwnd(),INSTANCEMAINWNDPROP);
CWnd::OnDestroy();
}
http://www.csdn.net/expert/topic/78/78172.shtm
在这里啦
#define INSTANCEMAINWNDPROP _T("your special string")
BOOL CYourApp::InitInstance()
{
if(CheckSingleInstance()==FALSE)
{
return FALSE; //则程序安全退出
}
//......
}
BOOL CYourApp::CheckSingleInstance()
{
::CreateMutex(NULL,TRUE,INSTANCEMAINWNDPROP);
if(::GetLastError()==ERROR_ALREADY_EXISTS)
{
//set focus to previous instance
CWnd* pPrevWnd=CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);
while(pPrevWnd)
{
if(::GetProp(pPrevWnd->GetSafeHwnd(),INSTANCEMAINWNDPROP))
{
if(pPrevWnd->IsIconic())
{
pPrevWnd->ShowWindow(SW_RESTORE);
}
pPrevWnd->SetForegroundWindow();
pPrevWnd->GetLastActivePopup()->SetForegroundWindow();
break;
}
pPrevWnd=pPrevWnd->GetWindow(GW_HWNDNEXT);
}
return FALSE;
}
return TRUE;
}
int CYourMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
::SetProp(GetSafeHwnd(),INSTANCEMAINWNDPROP,(HANDLE)1);
//......
}
void CYourMainWnd::OnDestroy()
{
::RemoveProp(GetSafeHwnd(),INSTANCEMAINWNDPROP);
CWnd::OnDestroy();
}
http://www.csdn.net/expert/topic/78/78172.shtm
在这里啦
#6
我是这样做的,不过不是最好的办法
BOOL CThread01App::InitInstance()
{
CMutex vMutex(FALSE,MUTEXNAME,NULL);
BOOL bResult;
HWND vShowWindow;
DWORD err;
bResult = vMutex.Lock(0); //判断实例是否已经启动
if (!bResult)
{
//是,则显示实例
vShowWindow = ::FindWindow(LPCTSTR("#32770"),LPCTSTR("Thread01"));
if (vShowWindow == NULL)
{
err = GetLastError();
exit(0);
}
::ShowWindow((HWND)vShowWindow,SW_SHOWNORMAL); //设置窗口属性
::SetForegroundWindow((HWND)vShowWindow); //设置窗口在最前面
exit(0);
}
...
}
在显示该实例的处理上不是很好,不知道有什么更好的方法,请指教!
BOOL CThread01App::InitInstance()
{
CMutex vMutex(FALSE,MUTEXNAME,NULL);
BOOL bResult;
HWND vShowWindow;
DWORD err;
bResult = vMutex.Lock(0); //判断实例是否已经启动
if (!bResult)
{
//是,则显示实例
vShowWindow = ::FindWindow(LPCTSTR("#32770"),LPCTSTR("Thread01"));
if (vShowWindow == NULL)
{
err = GetLastError();
exit(0);
}
::ShowWindow((HWND)vShowWindow,SW_SHOWNORMAL); //设置窗口属性
::SetForegroundWindow((HWND)vShowWindow); //设置窗口在最前面
exit(0);
}
...
}
在显示该实例的处理上不是很好,不知道有什么更好的方法,请指教!
#7
Q243953 HOWTO: Limit 32-bit Applications to One Instance Using C++
#8
利用注册表、互斥对象、原子、FindWindow、都可以!
#9
继续?
#10
关注!
#11
继续?
#12
贴上我的笔记:
方案一: 查找窗口类
方案二: 设置窗口属性
方案三: 使用文件映像
方案四: 使用原子
方案五: 使用同步对象
方案一: 使用注册类查找的方法实现单实例运行
例:
①C???App::InitInstance
BOOL C???App::InitInstance()
{
if (!FirstInstance())
return FALSE;
beRegisted=TRUE;
m_pMainWnd =new CMainWnd();
m_pMainWnd->CreateEx(0,"fmdmainwnd",
_T("CodeHelper"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
其中beRegisted为C???App成员
public:
BOOL beRegisted;
②C???App::FirstInstance
BOOL CMainApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd;
if (PrevCWnd = CWnd::FindWindow("fmdmainwnd",NULL))
{
ChildCWnd=PrevCWnd->GetLastActivePopup();
PrevCWnd->BringWindowToTop();
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE);
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop();
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}
③C???App::InitApplication
BOOL CMainApp::InitApplication()
{
CWinApp::InitApplication();
WNDCLASS wndcls;
//注册自定义类
memset(&wndcls, 0, sizeof(WNDCLASS));
//窗口基本类型
wndcls.style=CS_DBLCLKS ¦ CS_HREDRAW ¦ CS_VREDRAW;
wndcls.lpfnWndProc=::DefWindowProc;
wndcls.hInstance=AfxGetInstanceHandle();
wndcls.hIcon=LoadIcon(IDR_MAIN);
wndcls.hCursor=LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndcls.lpszMenuName=MAKEINTRESOURCE(IDR_MAIN);
wndcls.lpszClassName="fmdmainwnd";
return AfxRegisterClass(&wndcls);
}
④C???App::ExitInstance
int CMainApp::ExitInstance()
{
if(beRegisted)
::UnregisterClass("fmdmainwnd", AfxGetInstanceHandle());
return CWinApp::ExitInstance();
}
方案二:设置窗口附加属性 int C???Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
......
}
void C???Dlg::OnDestroy()
{
......
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
......
}
BOOL CEllipseWndApp::InitInstance()
{
// Create a Semaphore with a name of application exename
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;
}
C????Dlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
}
return FALSE;
}
方案三:使用文件映像
另文有述
方案四:使用原子
BOOL C???App::InitInstance()
{
.....
if(GlobalFindAtom("AdBreaker")) //找原子
return false;
ATOM GlobalAtom=GlobalAddAtom("AdBreaker"); //添加原子
CAdBreakerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
.....
GlobalDeleteAtom(GlobalAtom);
return FALSE;
}
方案五:使用同步对象 InitInstance中
HANDLE m_hMutex =
CreateMutex(NULL,TRUE,m_pszAppName);
if (GetLastError()==ERROR_ALREADY_EXISTS){
return FALSE;
}
另:在
http://www.csdn.net/expert/topic/159/159112.shtm
中liuqiannan(二迷糊) 的方案也不错:
回复人:liuqiannan(二迷糊) (2001-6-14 22:28:00) 得0分
用一个共享数据段,定义一个用来计数的长整形
#pragma data_seg(".OnlyOne")
long 1Count=-1;
#pragma data_seg()
用DEF文件定义共享属性
SECTIONS
.OnlyOne READ WRITE SHARED
在初始化阶段,如InitInstance开始处,加入
BOOL bFirstInit=(InterlockedIncrement($1InstanceCount)==0)
if(!bFirstInit)
{
AfxMessageBox("该程序已经运行",MB_OK¦MB_ICONSTOP);
InterlockedDecrement($1InstanceCount);
return FALSE;
}
程序结束后,调用:
InterlockedDecrement(&1InstanceCount);
综合,以上朋友的发言,应该有不少了,但只有少数能作到,将前一个实例激活
方案一: 查找窗口类
方案二: 设置窗口属性
方案三: 使用文件映像
方案四: 使用原子
方案五: 使用同步对象
方案一: 使用注册类查找的方法实现单实例运行
例:
①C???App::InitInstance
BOOL C???App::InitInstance()
{
if (!FirstInstance())
return FALSE;
beRegisted=TRUE;
m_pMainWnd =new CMainWnd();
m_pMainWnd->CreateEx(0,"fmdmainwnd",
_T("CodeHelper"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
其中beRegisted为C???App成员
public:
BOOL beRegisted;
②C???App::FirstInstance
BOOL CMainApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd;
if (PrevCWnd = CWnd::FindWindow("fmdmainwnd",NULL))
{
ChildCWnd=PrevCWnd->GetLastActivePopup();
PrevCWnd->BringWindowToTop();
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE);
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop();
return FALSE;
}
else
return TRUE; // First instance. Proceed as normal.
}
③C???App::InitApplication
BOOL CMainApp::InitApplication()
{
CWinApp::InitApplication();
WNDCLASS wndcls;
//注册自定义类
memset(&wndcls, 0, sizeof(WNDCLASS));
//窗口基本类型
wndcls.style=CS_DBLCLKS ¦ CS_HREDRAW ¦ CS_VREDRAW;
wndcls.lpfnWndProc=::DefWindowProc;
wndcls.hInstance=AfxGetInstanceHandle();
wndcls.hIcon=LoadIcon(IDR_MAIN);
wndcls.hCursor=LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndcls.lpszMenuName=MAKEINTRESOURCE(IDR_MAIN);
wndcls.lpszClassName="fmdmainwnd";
return AfxRegisterClass(&wndcls);
}
④C???App::ExitInstance
int CMainApp::ExitInstance()
{
if(beRegisted)
::UnregisterClass("fmdmainwnd", AfxGetInstanceHandle());
return CWinApp::ExitInstance();
}
方案二:设置窗口附加属性 int C???Dlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
::SetProp(m_hWnd, AfxGetApp()->m_pszExeName, (HANDLE)1);
......
}
void C???Dlg::OnDestroy()
{
......
::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
......
}
BOOL CEllipseWndApp::InitInstance()
{
// Create a Semaphore with a name of application exename
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;
}
C????Dlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
}
return FALSE;
}
方案三:使用文件映像
另文有述
方案四:使用原子
BOOL C???App::InitInstance()
{
.....
if(GlobalFindAtom("AdBreaker")) //找原子
return false;
ATOM GlobalAtom=GlobalAddAtom("AdBreaker"); //添加原子
CAdBreakerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
.....
GlobalDeleteAtom(GlobalAtom);
return FALSE;
}
方案五:使用同步对象 InitInstance中
HANDLE m_hMutex =
CreateMutex(NULL,TRUE,m_pszAppName);
if (GetLastError()==ERROR_ALREADY_EXISTS){
return FALSE;
}
另:在
http://www.csdn.net/expert/topic/159/159112.shtm
中liuqiannan(二迷糊) 的方案也不错:
回复人:liuqiannan(二迷糊) (2001-6-14 22:28:00) 得0分
用一个共享数据段,定义一个用来计数的长整形
#pragma data_seg(".OnlyOne")
long 1Count=-1;
#pragma data_seg()
用DEF文件定义共享属性
SECTIONS
.OnlyOne READ WRITE SHARED
在初始化阶段,如InitInstance开始处,加入
BOOL bFirstInit=(InterlockedIncrement($1InstanceCount)==0)
if(!bFirstInit)
{
AfxMessageBox("该程序已经运行",MB_OK¦MB_ICONSTOP);
InterlockedDecrement($1InstanceCount);
return FALSE;
}
程序结束后,调用:
InterlockedDecrement(&1InstanceCount);
综合,以上朋友的发言,应该有不少了,但只有少数能作到,将前一个实例激活
#13
用GUID做命名内核对象的名字,这样比较好
#14
呀,来晚了,那再说一种吧,
可以用内存映射文件实现:
MutexRuning为程序名
初始化阶段:
InitInstance中:
HANDLE hMap=CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,128,
"MutexRuning");
if(hMap==NULL)
{
AfxMessageBox("创建内存映射文件失败",MB_OK|MB_ICONSTOP);
return FALSE;
}
else if(GetLasError()==ERROR_ALREADY_EXISTS)
{
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
CString str=(char *)lpMem;
UnmapViewOfile(lpMem);
CloseHandle(hMap);
AfxMessageBox(str,MB_OK|MB_ICONSTOP);
return FALSE;
}
else
{
//是第一次运行
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
//程序运行描述信息
strcpy((char *) lpMem,"xxxx正在运行!");
UnmapViewOfFile(lpMem);
}
可以用内存映射文件实现:
MutexRuning为程序名
初始化阶段:
InitInstance中:
HANDLE hMap=CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,128,
"MutexRuning");
if(hMap==NULL)
{
AfxMessageBox("创建内存映射文件失败",MB_OK|MB_ICONSTOP);
return FALSE;
}
else if(GetLasError()==ERROR_ALREADY_EXISTS)
{
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
CString str=(char *)lpMem;
UnmapViewOfile(lpMem);
CloseHandle(hMap);
AfxMessageBox(str,MB_OK|MB_ICONSTOP);
return FALSE;
}
else
{
//是第一次运行
LPVOID lpMem=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
//程序运行描述信息
strcpy((char *) lpMem,"xxxx正在运行!");
UnmapViewOfFile(lpMem);
}
#15
Mutex可以做互斥,看看操作系统的书吧
#16
BOOL CXXXApp::InitInstance()
{
...
HANDLE m_hMutex=CreateMutex(NULL,TRUE, m_pszAppName);
if(GetLastError()==ERROR_ALREADY_EXISTS) {
AfxMessageBox("已经运行!");
return FALSE; }
...
}
{
...
HANDLE m_hMutex=CreateMutex(NULL,TRUE, m_pszAppName);
if(GetLastError()==ERROR_ALREADY_EXISTS) {
AfxMessageBox("已经运行!");
return FALSE; }
...
}