einzelne Instanz, mehrere dateien



  • hallo zusammen...

    Mein programm soll auf eine Instanz beschränkt sein. Das geht ja per Mutex recht einfach, wenn man so Sachen wie multiple Sessions dankbar ignoriert...

    Jetzt sollten zu öffnete Dateien natürlich auch an diese Instanz weitergeleitet werden, und da bin ich auf ein organisatorisches Problem gestoßen... Mein Gedanke war erst mal das Ganze einfach per FindWindow und SendMessage zu erledigen. Das klappt soweit auch, hat aber eine entscheidende Schwachstelle: Wenn man mehrere Dateien fast gleichzeitig öffnet (also im Explorer markiert und losschickt), versucht sich die zweite Instanz zu öffnen, lange bevor die erste es geschafft hat ein Fenster zu erstellen...

    Wenn ich ein Sleep(500); davorsetze klappts natürlich, aber das kann ja wohl das wahre nicht sein... (denn wer kann schon garantieren, dass das Fenster dann fertig ist?)

    Hat da jemand eine elegante Idee?
    Winamp schafft's ja auch 😉



  • Erstmal zum Thema FindWindow:
    http://www.c-plusplus.net/forum/viewtopic.php?t=48762

    Dann zu deinem Problem: der Mutex sollte gelockt bleiben, bis das Fenster steht....





  • peterchen schrieb:

    der Mutex sollte gelockt bleiben, bis das Fenster steht....

    Das heißt ich erstelle am Anfang den Mutex, warte bis ich in locken kann, schnappe mir dann das Fenster (wenn es keins gibt erstelle ich es selbst) und schicke die Nachricht...
    Dann müsste ich den vor Schließen des Fensters allerdings auch wieder locken, damit sich keine zweite Instanz aufbaut, während die erste noch aufräumt.
    Sollte funktionieren...

    Allerdings scheinen die in dem Thread von dir erwähnten Named Pipes eher nach meinem Geschmack zu sein. Damit würde das FindWindow-Problem gleich wegfallen (obwohl ich ohnehin schon hässliche Pickel habe 😉 tja, jetzt weiß ich wenigstens wovon ;). Gibt es für Pipes zufällig so etwas wie eine notify-Nachricht, die sich meldet, sobald etwas hineingeschrieben wurde? Oder braucht meine Anwendung noch nen Thread... *seufz*? 😉



  • soo... endlich mal Zeit gefunden und implementiert. Ich poste es einfach mal, vielleicht hilfts ja mal jemandem...

    Das Programm wird nur einmal ausgeführt, weitere Instanzen schicken die übergebenen Dateien an die Hauptinstanz, welche sie in einer Messagebox ausgibt. (Hat die erste Instanz auch schon eine Datei in der Kommandozeile, so wird die auch in die Pipe geschrieben, damit das Abarbeiten an einer Stelle erfolgen kann)

    Evtl. noch hinzuzufügen wäre Sicherheitsfeatures.
    (und der Namen der Pipe sollte natürlich angepasst werden 😉

    HANDLE g_hPipe;
    const TCHAR g_szAppName[] = _T("PipeDemo");
    
    bool WriteToPipe(const TCHAR *szText, WORD wLength) {
    
    	WaitNamedPipe(_T("\\\\.\\pipe\\{4877A107-15E6-4c4c-AE41-F07F4B82D1C4}"), 5000);
    	HANDLE hPipe = CreateFile(_T("\\\\.\\pipe\\{4877A107-15E6-4c4c-AE41-F07F4B82D1C4}"),
    							  GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
    							  FILE_ATTRIBUTE_NORMAL, NULL);
    	if (hPipe == INVALID_HANDLE_VALUE)
    		// give up
    		return false;
    
    	// write to pipe
    	DWORD dwCheck;
    	WriteFile(hPipe, &wLength, sizeof(wLength), &dwCheck, NULL);
    	WriteFile(hPipe, szText, wLength * sizeof(TCHAR), &dwCheck, NULL);
    	CloseHandle(hPipe);
    	return true;
    
    	}
    
    unsigned int CALLBACK PipeThread(void *pParam) {
    
    	WORD wLength;
    	DWORD dwCheck;
    
    	// keep reading pipe
    	while (true) {
    
    		if (!(ConnectNamedPipe(g_hPipe, NULL) ? 
    			true:(GetLastError() == ERROR_PIPE_CONNECTED)))
    			break;
    
    		wLength = 0;
    		ReadFile(g_hPipe, &wLength, sizeof(wLength), &dwCheck, NULL);
    
    		wLength++; // add 0 at end
    		TCHAR *pText = new TCHAR[wLength];
    		pText[wLength-1] = 0;
    
    		ReadFile(g_hPipe, pText, wLength * sizeof(TCHAR), &dwCheck, NULL);
    
    		DisconnectNamedPipe(g_hPipe);
    
    		if (pText[0] == ':') {
    			// parameter
    			CloseHandle(g_hPipe);
    			delete[] pText;
    			break;
    			}
    
    		MessageBox(NULL, pText, g_szAppName, MB_OK);
    
    		delete[] pText;
    		}
    
    	return 0;
    
    	} // PipeThread
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, TCHAR *szCmdLine, int nShowCmd) {
    
    	/*
    	// simulate input
    	TCHAR input[] = "test.file";
    	szCmdLine = input;
    	*/
    
    	// create pipe for processing of cmdline params
    	g_hPipe = CreateNamedPipe(_T("\\\\.\\pipe\\{4877A107-15E6-4c4c-AE41-F07F4B82D1C4}"),
    							  PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE,
    							  0, 1, 0, 0, NMPWAIT_WAIT_FOREVER, NULL);
    
    	if (g_hPipe != INVALID_HANDLE_VALUE) {
    		// main instance, create pipe reader
    		UINT id;
    		HANDLE hPipeThread = (HANDLE)_beginthreadex(NULL, 0, PipeThread, NULL, 0, &id);
    		}
    
    	if (*szCmdLine) {
    
    		// add file name into pipe
    		WORD wLength = lstrlen(szCmdLine);
    
    		// remove "" around file name if there
    		if (szCmdLine[0] == '"') {
    			wLength--;
    			szCmdLine[wLength] = 0;
    			szCmdLine++;
    			wLength--;
    			}
    
    		if (szCmdLine[0] != ':')
    			// can't accept ':' because used internally to abort thread
    			WriteToPipe(szCmdLine, wLength);
    		}
    
    	if (g_hPipe == INVALID_HANDLE_VALUE)
    		// only pass on file name to main process and nothing more
    		return 0;
    
    	/*
    	window handling goes here
    	*/
    
    	// abort PipeThread
    	WriteToPipe(":", 1);
    	return 0;
    
    	}
    

Anmelden zum Antworten