2010-11-16 31 views
10

Tôi có một ứng dụng sử dụng kết nối ổ cắm để gửi và nhận dữ liệu từ một ứng dụng khác. Trong khi tạo socket, nó sử dụng cổng 4998.Làm thế nào để chạy chỉ một thể hiện của ứng dụng

Đó là vấn đề của tôi. Khi tôi khởi động ứng dụng của mình, socket sẽ bắt đầu sử dụng cổng 4998. Vì vậy, nếu tôi muốn thực thi lại ứng dụng thì tôi gặp lỗi ràng buộc socket.

Vì vậy, tôi muốn giới hạn phiên bản ứng dụng của tôi thành một. Điều đó có nghĩa là nếu ứng dụng đã chạy và một số ứng dụng sẽ chạy lại ứng dụng bằng cách nhấn vào biểu tượng exe hoặc shortcut, nó sẽ không chạy chương trình, thay vào đó nó sẽ đưa ứng dụng hiện có lên trên cùng.

Trả lời

10

Bạn có thể sử dụng mutex được đặt tên.

Mã mẫu từ article:

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; 
} 
+12

Bằng cách gọi OpenMutex() trước tiên, bạn có một điều kiện chủng tộc. Hãy gọi hàm CreateMutex/Ex() trước tiên. Nó sẽ cho bạn biết nếu mutex đã tồn tại. Gọi OpenMutex() chỉ khi CreateMutex() không thành công với lỗi ERROR_ACCESS_DENIED. –

+0

Bất kỳ mẹo nào về cách thực hiện công việc này trên Win7 +? Global \ x mutexes không nhìn thấy nhau từ phiên đăng nhập người dùng khác nhau ... –

+1

@ RomanPlášil họ thực sự làm, bạn phải làm điều gì đó sai – paulm

3

Tạo sự kiện có tên khi bắt đầu và kiểm tra kết quả. Đóng ứng dụng nếu sự kiện đã tồn tại.

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; 
} 

Đóng m_hStartEvent khi thoát ứng dụng.

+0

Nếu CreatEvent() không thành công, bạn không thể biết ứng dụng có đang chạy hay không, vì vậy bạn nên thoát, không tiếp tục. –

1

Đừng bạn đã có một cách để kiểm tra xem ứng dụng của bạn đang chạy? Ai cần một Mutex, nếu cổng đã được thực hiện, bạn biết rằng ứng dụng đang chạy!

+0

Có Bây giờ tôi thay vì hiển thị lỗi tôi cần phải mang ứng dụng của mình bằng cách sử dụng quy trình ID. Bất kỳ giúp đỡ? – Simsons

+5

Chỉ vì cổng đang được sử dụng, điều đó không có nghĩa là ứng dụng CỦA BẠN đang sử dụng nó. –

+0

@ OJ, Good Catch. Cổng có thể được sử dụng bởi ứng dụng som eother – Simsons

4

/* Tôi đã tìm thấy việc chỉnh sửa cần thực hiện. Đã thêm một số mã bổ sung và các chỉnh sửa cần thiết. Người hiện tại đang làm việc hoàn hảo cho tôi. Cảm ơn bạn, Kirill V. Lyadvinsky và Remy Lebeau vì sự giúp đỡ !!

*/

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; 
} 

/* Đoạn mã trên làm việc ngay cả khi một cố gắng để mở ra trường hợp thứ hai TỪ đăng nhập khác rời khỏi ĐẦU ĐĂNG NHẬP MỞ với cá thể của nó chạy. */

2

Khi ứng dụng của bạn khởi tạo, hãy tạo một mutex. Nếu nó đã tồn tại, hãy tìm ứng dụng hiện có và đưa nó vào nền trước. Nếu ứng dụng có một tiêu đề cố định cho cửa sổ chính của nó, nó rất dễ tìm với FindWindow.

m_singleInstanceMutex = CreateMutex(NULL, TRUE, L"Some unique string for your app"); 
if (m_singleInstanceMutex == NULL || 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. 
} 
Các vấn đề liên quan