Verhindern, dass derselbe Prozess mehrmals gestartet wird
-
Wie? Mutex?
-
Jepp, ist eine Möglichkeit
HANDLE hMutex = CreateMutex(0,0,TEXT("MY_APP")); if(GetLastError()==ERROR_ALREADY_EXISTS) { // Eine Instanz ist vorhanden, jetzt mit FindWindow o.ä. das Fenster suchen }Hinterher wird der Mutex per ReleaseMutex(hMutex) wieder freigegeben.
-
Ich habe es in mein Programm am Anfang eingefügt und es 2 mal gestartet. Trotzdem startete es 2 mal... Wie implementiere ich dein Beispiel?
Danke.
-
Wird dein Mutex denn gefunden? Hast du eine Messagebox ausgegeben, wenn es gefunden wird?
Normalerweise sucht man das Fenster, prüft ob es minimiert ist, setzt es in den Vordergrund und überprüft, ob Argumente mit WinMain mitgegeben wurden. Wenn ja, dann muss jetzt irgendeine Funktion zum Öffnen der Dateien aufgerufen werden.
Das Wichtigste aber ist, dass am Ende der if-Abfrage ein return 0; stehen muss.
-
GetLastError() gibt auch beim 2. Start 0 aus.
-
Ich habe gerade nochmal nachgeschaut.
Erstens darf natürlich keine Funktion aufgerufen werden, lpCmd muss in die Zwischenablage kopiert werden und dem Fenster mitgeteilt werden (per SendMessage), dass es sich etwas aus der Zwischenablage holen soll.
Zweitens verstehe ich nicht, dass ERROR_SUCCESS zurückgegeben wird. Hast du mal einen aussagekräftigeren Namen als My_App probiert? Wahrscheinlich, ich kann es mir nicht erklären. Unter XP und Win 7 funktioniert es bei mir so problemlos. Vista->keine Ahnung, vermutlich auch.
Hier mal mein Originalcode aus einer MDI-Anwendung:#ifndef LEO_DEBUG HANDLE h = CreateMutex(0,0,TEXT("LEO_DIB_EDIT_RELEASE")); // !=0, auch wenn ein Mutex mit dem Namen bereits existiert. #else HANDLE h = CreateMutex(0,0,TEXT("LEO_DIB_EDIT_DEBUG")); #endif if(GetLastError()==ERROR_ALREADY_EXISTS) // Die einzige Möglichkeit { HWND hwndPrev; if((hwndPrev=FindWindow(leoDibEdit::szCLDEMDIWindowClassName,0))!=0) { if(IsIconic(hwndPrev)) { ShowWindow(hwndPrev,SW_RESTORE); } SetForegroundWindow(hwndPrev); if(strlen(lpCmdLine)>0) { L_String str(lpCmdLine); leo_ut::ReplaceAll(&str,TEXT("\"")); if(OpenClipboard(hwndPrev)) { HGLOBAL hGlobal = leo_ut::CreateDropHandle(str); EmptyClipboard(); SetClipboardData(CF_HDROP, hGlobal); CloseClipboard(); SendMessage(hwndPrev,LM_DROPFROMCLIPBOARD,0,0); } } } else { // ??? neue Instanz trotzdem erstellen ? } ReleaseMutex(h); return 0; } }Es werden natürlich einige Hilfsfunktionen aufgerufen, dies ist aber nicht entscheidend.
-
Es geht. Vielen Dank. Komischerweise aber erst nach Neustart...
-
Vicious Falcon schrieb:
lpCmd muss in die Zwischenablage kopiert werden
Und wie viele Benutzer haben sich bei dir schon dafür bedankt, dass du ihnen den Inhalt der Zwischenablage zerschossen hast? Gib die Aufrufparameter mittels WM_COPYDATA weiter.
-
Oder einfach Shared Memory block verwenden....
Diese Lösungverwendet auch WM_COPYDATA:
http://www.naughter.com/sinstance.htmlAnsonsten:
http://www.codeproject.com/KB/cpp/avoidmultinstance.aspx
http://www.flounder.com/nomultiples.htm
http://vcfaq.mvps.org/mfc/2.htm
-
Mir ist das nicht aufgefallen, da der Code erstens schon recht alt ist und zweitens ich so gut wie nie in diese Situation komme. Ich habe es jetzt geändert.
Danke für die (berechtigte) Kritik!