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=48762Dann 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 werdenHANDLE 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; }