我有一个应用程序,它使用套接字连接从另一个应用程序发送和接收数据。创建套接字时,它使用端口 4998 。
这就是我的问题所在。一旦我启动我的应用程序,套接字就会开始使用端口 4998。因此,如果我想再次执行该应用程序,则会出现套接字绑定错误。
所以我想将我的应用程序实例限制为一个。这意味着,如果应用程序已经在运行,并且有人尝试通过单击 exe 或快捷方式图标再次运行该应用程序,则它不应运行该程序,而应将现有应用程序置于顶部。
当您的应用程序初始化时,创建一个互斥体。如果已经存在,则找到现有应用程序并将其置于前台。如果应用程序的主窗口有固定标题,则可以使用
FindWindow
轻松找到。
m_singleInstanceMutex = CreateMutex(NULL, TRUE, L"Some unique string for your app");
if (GetLastError() == ERROR_ALREADY_EXISTS) {
HWND existingApp = FindWindow(0, L"Your app's window title");
if (existingApp) SetForegroundWindow(existingApp);
return FALSE; // Exit the app. For MFC, return false from InitInstance.
}
您可以使用命名互斥体。
来自文章的代码示例:
WINAPI WinMain(
HINSTANCE, HINSTANCE, LPSTR, int)
{
try {
// Try to open the mutex.
HANDLE hMutex = OpenMutex(
MUTEX_ALL_ACCESS, 0, "MyApp1.0");
if (!hMutex)
// Mutex doesn’t exist. This is
// the first instance so create
// the mutex.
hMutex =
CreateMutex(0, 0, "MyApp1.0");
else
// The mutex exists so this is the
// the second instance so return.
return 0;
Application->Initialize();
Application->CreateForm(
__classid(TForm1), &Form1);
Application->Run();
// The app is closing so release
// the mutex.
ReleaseMutex(hMutex);
}
catch (Exception &exception) {
Application->
ShowException(&exception);
}
return 0;
}
/* 我发现需要进行必要的编辑。添加了一些所需的额外代码和编辑。目前的一款非常适合我。谢谢基里尔·V·利亚德文斯基和雷米·勒博的帮助!
*/
bool CheckOneInstance()
{
HANDLE m_hStartEvent = CreateEventW( NULL, FALSE, FALSE, L"Global\\CSAPP" );
if(m_hStartEvent == NULL)
{
CloseHandle( m_hStartEvent );
return false;
}
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
CloseHandle( m_hStartEvent );
m_hStartEvent = NULL;
// already exist
// send message from here to existing copy of the application
return false;
}
// the only instance, start in a usual way
return true;
}
/* 即使当用户尝试从不同的登录名打开第二个实例而使第一个登录名保持打开状态且其实例正在运行时,上述代码仍然有效。 */
在开始时创建命名事件并检查结果。如果事件已存在,请关闭应用程序。
BOOL CheckOneInstance()
{
m_hStartEvent = CreateEventW( NULL, TRUE, FALSE, L"EVENT_NAME_HERE" );
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
CloseHandle( m_hStartEvent );
m_hStartEvent = NULL;
// already exist
// send message from here to existing copy of the application
return FALSE;
}
// the only instance, start in a usual way
return TRUE;
}
在应用程序退出时关闭
m_hStartEvent
。
您可以在 WindowMain 函数中通过从一开始就使用类名和主窗口标题调用 FindWindow 函数来实现此目的。如果窗口存在,您可以向用户显示消息或简单地显示窗口然后返回:
HWND hWnd = FindWindow(lzClassName, lzWindowText);
if(hWnd!=NULL)
{
ShowWindow(hWnd, SW_SHOW);
return 0;
}
WNDCLASSEX wcex;
/* register window class */
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
...
您是否已经有办法检查您的应用程序是否正在运行?谁需要互斥锁,如果端口已经被占用,你就知道应用程序正在运行!