1.创建新节法
为程序加入一个全局变量,让这个全局变量可以被程序的多个实例所共享,每当程序实例运行时就对该全局变量进行修改。通过访问该全局变量,就可以知道有多少个实例在运行了。当然,为了系统的安全和稳定性,默认情况下是不允许这样做得。为了阻止这种事情的发生,系统使用了copy-on-write(写入时拷贝)机制,不过我们可以使用创建新节的方法来绕过它。
1.创建节
- #pragma data_seg("Shared")
- BOOL bExist = FALSE; //已经初始化变量
- int num; //未初始化变量
- #pragma data_seg()
#pragma data_seg("Shared")
BOOL bExist = FALSE; //已经初始化变量
int num; //未初始化变量
#pragma data_seg()
注:在创建节的过程中,编译器只将已经初始化的变量放入新节中。
2.将初始化或未初始化的数据放入希望的任何节中
- __declspec(allocate("Shared")) int num2 = 0; //添加初始化的变量
- __declspec(allocate("Shared")) int num3; //添加未初始化的变量
__declspec(allocate("Shared")) int num2 = 0; //添加初始化的变量
__declspec(allocate("Shared")) int num3; //添加未初始化的变量
注:在向节中添加数据之前必须先创建该节。
3.设置节的属性
- #pragma comment(linker, "/Section:Shared,RWS")
#pragma comment(linker, "/Section:Shared,RWS")
注:节的属性包括RWS,其中R代表READ,W代表WEITE,S代表SHARED。
使用:
- #pragma data_seg("Shared")
- HWND hWnd=NULL;
- #pragma data_seg()
- #pragma comment(linker, "/Section:Shared,RWS")
#pragma data_seg("Shared")
HWND hWnd=NULL;
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,RWS")
初始化函数中:
- if (hWnd==NULL)
- {
- hWnd=m_hWnd;
- }
- else
- {
- AfxMessageBox(_T("只允许运行一个实例!"));
- ::SetForegroundWindow(hWnd);
- ExitProcess(0);
- }
if (hWnd==NULL)
{
hWnd=m_hWnd;
}
else
{
AfxMessageBox(_T("只允许运行一个实例!"));
::SetForegroundWindow(hWnd);
ExitProcess(0);
}
2.互斥体法
缺点是无法激活旧窗口
- hObject=CreateMutex(NULL,FALSE,_T("互斥体"));
- if (GetLastError()==ERROR_ALREADY_EXISTS)
- {
- AfxMessageBox(_T("只允许运行一个实例!"));
- ExitProcess(0);
- }
hObject=CreateMutex(NULL,FALSE,_T("互斥体"));
if (GetLastError()==ERROR_ALREADY_EXISTS)
{
AfxMessageBox(_T("只允许运行一个实例!"));
ExitProcess(0);
}
3.查找窗口标题法
1.FindWindow
初始化函数中
- HWND hWnd=::FindWindow(NULL,_T("FindWindow单实例"));
- if (hWnd!=NULL)
- {
- AfxMessageBox(_T("只允许运行一个实例!"));
- ::SetForegroundWindow(hWnd);
- ExitProcess(0);
- }
- SetWindowText(_T("FindWindow单实例"));
HWND hWnd=::FindWindow(NULL,_T("FindWindow单实例"));
if (hWnd!=NULL)
{
AfxMessageBox(_T("只允许运行一个实例!"));
::SetForegroundWindow(hWnd);
ExitProcess(0);
}
SetWindowText(_T("FindWindow单实例"));
2.EnumWindows
- BOOL CALLBACK MyEnumWndProc(HWND hwnd,LPARAM lParam)
- {
- TCHAR szCaption[256]={0};
- GetWindowText(hwnd,szCaption,256);
- if (_tcscmp(_T("EnumWindows单实例"),szCaption)==0)
- {
- AfxMessageBox(_T("只允许运行一个实例!"));
- ::SetForegroundWindow(hwnd);
- ExitProcess(0);
- }
- return TRUE;
- }
BOOL CALLBACK MyEnumWndProc(HWND hwnd,LPARAM lParam)
{
TCHAR szCaption[256]={0};
GetWindowText(hwnd,szCaption,256);
if (_tcscmp(_T("EnumWindows单实例"),szCaption)==0)
{
AfxMessageBox(_T("只允许运行一个实例!"));
::SetForegroundWindow(hwnd);
ExitProcess(0);
}
return TRUE;
}
初始化函数中
- EnumWindows(MyEnumWndProc,NULL);
- SetWindowText(_T("EnumWindows单实例"));
EnumWindows(MyEnumWndProc,NULL);
SetWindowText(_T("EnumWindows单实例"));
3.GetWindow
- TCHAR szCaption[MAX_PATH]={0};
- HWND hWnd=::GetWindow(::GetDesktopWindow(), GW_CHILD);
- while(hWnd!=NULL)
- {
- ::GetWindowText(hWnd,szCaption,MAX_PATH);
- if (_tcscmp(_T("GetWindow单实例"),szCaption)==0)
- {
- AfxMessageBox(_T("只允许运行一个实例!"));
- ::SetForegroundWindow(hWnd);
- ExitProcess(0);
- }
- hWnd=::GetWindow(hWnd, GW_HWNDNEXT);
- }
- SetWindowText(_T("GetWindow单实例"));
TCHAR szCaption[MAX_PATH]={0};
HWND hWnd=::GetWindow(::GetDesktopWindow(), GW_CHILD);
while(hWnd!=NULL)
{
::GetWindowText(hWnd,szCaption,MAX_PATH);
if (_tcscmp(_T("GetWindow单实例"),szCaption)==0)
{
AfxMessageBox(_T("只允许运行一个实例!"));
::SetForegroundWindow(hWnd);
ExitProcess(0);
}
hWnd=::GetWindow(hWnd, GW_HWNDNEXT);
}
SetWindowText(_T("GetWindow单实例"));
4.枚举进程法
1.定时器一直去监视有没有相同进程名字,发现则发送WM_CLOSE消息关闭窗口
2.初始化时枚举进程,配合挂钩queryinfomation的内核函数,修改自己的进程名字