![]() |
Verhindern das die gleich Exe gestartet wird
Moint,
also mittlerweile weiß ich wie ich verhindern kann, dass zweimal das gleich Programm gestartet wird. Habe das mit der marix-Methode realisiert (hoffe die sagt jemandem was, hab sie aber glaub ich auch aus diesem Forum). Nun will ich aber nicht generell verhindern, dass mein Programm zweimal gestartet wird, sondern nur dass die gleiche exe zweimal gestartet wird. Sprich, wenn ich 2 identische Exe habe, wovon einen nr1.exe heißt und eine nr2.exe, dann soll ein Doppelstart möglich sein. Habe ich jedoch 2 Exes mit dem gleichen Namen nr1.exe und nr1.exe soll ein Merhfachstart verhindert werden. Dies alles soll unabhängig sein von den Pfaden in denen die exe-Dateien liegen. Hat hierzu jemand ne Lösung ? weiß nämlich irgendwie nciht recht wie ich das machen soll?!?! |
Re: Verhindern das die gleich Exe gestartet wird
Hai meisteralex,
deine "marix-Methode" kenn ich nicht. Ich mache das immer mit einem Mutex so wie ![]() Jetzt kannst Du ja als "String für den Mutex" einfach den Namen der Exe plus einer GUID verwenden.
Delphi-Quellcode:
begin
. . mutexstring := '{1F31C742-E52D-4EC0-8632-02BEAFA3337E}' + ExtractFileName(ParamtStr(0)); mHandle := CreateMutex(nil,True,mutexstring); . . end; |
Re: Verhindern das die gleich Exe gestartet wird
Wenn Du die EXE selbst geschrieben hast, dann würd ich das auch über 'Mutexe' abbilden. Wenn nicht, hilft Dir 'FindWindows' weiter. Es liefert Dir, sofern vorhanden, das Handle eines Fensters mit einer bestimmten Titelzeile und einem Klassennamen. Wenn FindWindows einen Wert<>0 liefert, läuft das Programm schon.
Du musst nur noch rausfinden, wie die Fensterklasse (und ggf. der Titel) des Hauptfensters der Anwendung heisst. Dafür verwende ich EnumWindows. Ich hab mir mal ein kleines Programm geschrieben, das die Fenstertitel und Fensterklassen auflistet. Check mal EnumWindows, das ist dann ganz einfach. |
Re: Verhindern das die gleich Exe gestartet wird
genau, meinte auch mutex
genau so habe ich es auch schon probiert, als argument habe ich den konstaten string gegen den paramstr(0), also den exe-namen ausgetauscht. Wozu ist die GUID denn noch nötig? Wenn ich den EXE-Namen mit Hilfe von parmastr(0) als Argument der CreateMutex - Anweisung übergebe kann ich auch 2 mal die gleiche Datei ausführen, der "mehrfachstar-verhinderungs-effekt" ist also vollkommen weg. Hat das irgendwas mit der GUID zu tun`? |
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
bitte beachte aber das Du mit ParamStr(0) nicht nur den Exe-Namen sondern auch den Pfad zu dieser bekommst. Wenn die selbe Exe in zwei Verzeichnissen liegt hast Du verschiedene Strings. Zitat:
|
Re: Verhindern das die gleich Exe gestartet wird
Es war aber eine Datei aus dem gleichen Verzeichnis, welche sich auch 2 mal aufrufen ließe.
Jemand ne Ahnung warum ? Das mit der GUID ist logisch, aber ich könnte genau so gut einen anderen eindeutigen String nehmen oder? |
Re: Verhindern das die gleich Exe gestartet wird
Moin...
ich hab das folgendermassen realisiert :
Delphi-Quellcode:
und halt oben noch mhandle als thandle deklariert.
initialization
mHandle := CreateMutex(nil, true, 'meinprogramm'); if (GetLastError = Error_Already_Exists) then halt; finalization if mHandle <> 0 then CloseHandle(mHandle); Das wars bei mir soweit und geht. MFG Carsten |
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
Du willst ja dass 2 verschieden namige Echsen auch starten dürfen. |
Re: Verhindern das die gleich Exe gestartet wird
Delphi-Quellcode:
So das ist mein Code und trotzdem lässt sich eine EXE in meinem falle ist das (C:\hey.exe) 2x starten, bziehungsweise beliebig oft starten
unit mulex;
interface implementation uses windows,Dialogs,sysutils; var mHandle: THandle; Initialization mHandle := CreateMutex(nil,True,paramstr(0)); // 'xxxxx' Der Anwendungsname ist hier einzutragen if GetLastError = ERROR_ALREADY_EXISTS then begin // Anwendung läuft bereits showMessage('Anwendung läuft bereits!!!!!'); Halt; end; finalization if mHandle <> 0 then CloseHandle(mHandle) end. {Dieter Hirt} |
Re: Verhindern das die gleich Exe gestartet wird
Hmm... das ist ja seltsam.
Wenn man den Code aus der Code-Library nimmt und als "String" ParamStr(0) verwendet funktioniert es nicht.
Delphi-Quellcode:
mString := ParamStr(0); // So geht es nicht
mHandle := CreateMutex(nil, True, PAnsiChar(mString)); mString := 'blubber'; // so geht es mHandle := CreateMutex(nil, True, PAnsiChar(mString)); |
Re: Verhindern das die gleich Exe gestartet wird
Ich wuerde nicht paramstr(0) als mutex-object Name nehmen, ansonsten laesst sich die EXE aus einem anderen Verzeichnis auch starten.
|
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
am anfang steht: Zitat:
Darum habe ich in meinem ersten Posting ja auch geschrieben das mit ![]() Nachtrag So geht es übgrigens:
Delphi-Quellcode:
Aber warum geht es nicht wenn ich "nur" mit ParamStr(0) arbeite?
mString := '{8F9B886B-444C-47B3-934E-8A2780F01B62}' + ExtractFileName(ParamStr(0));
mHandle := CreateMutex(nil, True, PAnsiChar(mString)); |
Re: Verhindern das die gleich Exe gestartet wird
@toms: genau das ist mein wille, also es sollen z.b. C:\hey.exe und C:\test\hey.exe gleichzeitig laufen können
@sharky: Zitat:
und wie mache ich es dann, wenn nicht so?:
Delphi-Quellcode:
mString := ParamStr(0); // So geht es nicht
mHandle := CreateMutex(nil, True, PAnsiChar(mString)); |
Re: Verhindern das die gleich Exe gestartet wird
Probier mal diesen Code, den Du hinter Application.Title := ... deines Projets ausführst. Klappt bei mir einwandfrei. Und wenn die Anwendung bereits läuft, wird ein Zweitstart nicht nur unterbunden sondern die bereits laufende Anwendung wird automatisch nach vorne gebracht:
Delphi-Quellcode:
unit OneInst;
interface { Make a call to this procedure in your project source immediately before the first call to CreateForm. That should ensure it is after the Application.Title assignment that can muck up the logic. If you haven't set an application title yet, then do so to ensure this works } procedure EnsureSingleInstance (MyGUID : string) ; implementation uses WinTypes, WinProcs, Forms, SysUtils, Messages; procedure EnsureSingleInstance (MyGUID : string) ; var Wnd: HWnd; WndClass, WndText: array[0..255] of char; begin {$ifdef Win32} { Try and create a semaphore. If we succeed, then check } { if the semaphore was already present. If it was } { then a previous instance is floating around. } { Note the OS will free the returned semaphore handle } { when the app shuts so we can forget about it } if (CreateSemaphore(nil, 0, 1, PChar(MyGUID)) <> 0) and (GetLastError = Error_Already_Exists) then {$else} if HPrevInst <> 0 then {$endif} begin Wnd := GetWindow(Application.Handle, gw_HWndFirst); while Wnd <> 0 do begin { Look for the other TApplication window out there } if Wnd <> Application.Handle then begin { Check it's definitely got the same class and caption } GetClassName(Wnd, WndClass, Pred(SizeOf(WndClass))); GetWindowText(Wnd, WndText, Succ(Length(Application.Title))); if (StrPas(WndClass) = Application.ClassName) and (StrPas(WndText) = Application.Title) then begin { This technique is used by the VCL: post } { a message then bring the window to the } { top, before the message gets processed } PostMessage(Wnd, wm_SysCommand, sc_Restore, 0); {$ifdef Win32} SetForegroundWindow(Wnd); {$else} BringWindowToTop(Wnd); {$endif} Halt end end; Wnd := GetWindow(Wnd, gw_HWndNext) end end end; end. |
Re: Verhindern das die gleich Exe gestartet wird
@jelly
wie verhält sich dein code wenn ich ne copy der exe starten will? also z.b. c:\test.exe und c:\test\test.exe ? |
Re: Verhindern das die gleich Exe gestartet wird
AusZug aus dem EasyDelphiHelper:
Zitat:
|
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
hast Du dir mal den gesamten Thread durchgelesen? Das mit dem Mutex haben wir ja schon im ersten Posting geklärt. |
Re: Verhindern das die gleich Exe gestartet wird
Oh Sorry, es schien mir einfach nochnicht gelöst geworden zu sein, deswegen hab ich das gepostet :oops: , bei mir funzt das tadellos.
|
Re: Verhindern das die gleich Exe gestartet wird
ja bei mir ja auch, das eigentlich problem ist, dass sich nur die exakt gleiche exe nicht 2 mal starten lassen soll.
mit exakt gleich meine ich, das es die selbe ist, und nicht die gleiche! nochmal: C:\test.exe soll nicht 2 mal aufgerufen werden können C:\test.exe und C:\test\test.exe sollen jedoch gleichzeitig aufgerufen werden können, wobei hier C:\test.exe und C:\test\test.exe identische Dateien sind |
Re: Verhindern das die gleich Exe gestartet wird
Sorge dafür dass du eine entsprechende GUID verwendest. Wenn du die Echsen aus 2 unterschiedlichen Verz. starten lassen willst, muss auf jeden Fall der Verzeichnispfad mit rein.
Also z.B.
Delphi-Quellcode:
EnsureSingleInstance ('{8F9B886B-444C-47B3-934E-8A2780F01B62}' + application.Exename) ;
|
Re: Verhindern das die gleich Exe gestartet wird
Du könntest bei Programmstart Das WindowCaption auf den Programmpfad ändern und ('Test.exe:C:\test\test.exe') und prüfen ob ein Programm mit selbigen Fenstercaption existiert.(Weis nich ob sowas möglich ist, aber wenn dann müsste es gehen.)Wenn eins existiert dann schliesst du dein Prog.
|
Re: Verhindern das die gleich Exe gestartet wird
das wäre auch ne idee
jemand beispielcode wie ich nach einem fenster mit dem namen 'C:\test\test.exe' suche ? wie verhält sich das ganze, wenn die form mit form.visible = false auf unsichtbar steht ? |
Re: Verhindern das die gleich Exe gestartet wird
hmm.. die Form existiert trotzdem, denke ich also auch die FormCaption. Aber wie das geht, musst vielelicht mal die Forensuche bemühen
![]() |
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
Auf diese oder ähnliche Weise könntest Du eine Liste erzeugen und kontollieren. Mal eine andere Frage: Ich möchte im Fall eines doppelt gestarteten Programms das schon vorhandene in den Vordergrund rücken (mit GetWindow oder FindWindow). Dabei habe ich noch nicht verstanden, wie ich alle gestarteten Programme mit dem Programmnamen finde (ich bekomme immer das Handle, was ich eigentlich gerade abschießen wollte). Grüße, Messie. |
Re: Verhindern das die gleich Exe gestartet wird
Das mit der Datei ist sogar nochbesser, eine Textdatei die am anfang in ne stringlist geladen wierd, dann wird geprüft ob ParamStr(0) schon drinsteht, wenn ja prog beenden, wenn nein ParamStr(0) reinschreiben.
|
Re: Verhindern das die gleich Exe gestartet wird
Wenn ich aber einen Eintrag in der Reg mache oder eine Datei erzeuge habe ich das Problem das dies auch noch vorhanden ist wenn sich zum Beispiel der Rechner aufhängt und ich neu starten muss. -> Man könnte das Programm nie mehr starten.
Bei einem Mutex passiert dies nicht. |
Re: Verhindern das die gleich Exe gestartet wird
man kann doch prüfen wann die Datei erstellt wurde/der Rechner neu gestartet wurde und falls die Datei älter ist diese löschen und neu erstellen.
|
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
In einem Listeneintrag könnte man auch das Handle mit abspeichern und die Prüfung machen, ob dieses Handle gerade aktiv ist. Damit müßte ich doch alle ungültigen Einträge löschen können.. Grüße, Messie |
Re: Verhindern das die gleich Exe gestartet wird
das ist eine richtige scheiss idee :P was ist wenn das prog abstürzt? dann bleibt der string drin und man kann es nicht mehr starten. dann muss man es per hand aus der datei austragen
das mit dem mutex ist schon in ordnung. ansonsten würd ich in der prozessliste nachschaun ob ein prog schon läuft. Process32First / Process32Next in der unit tlhelp32 schau dir das mal an
Delphi-Quellcode:
function FindProcess(ExeNames: string): integer; stdcall;
function DeleteExe(s: string): string; var i, j: integer; begin setlength(result,length(s)); result := ''; j := 0; for i := 1 to length(s) do begin if (copy(s,i,6) = ('.EXE'#13#10)) then j := 4; if (j > 0) then dec(j) else result := result+s[i]; end; end; var FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; ContinueLoop: BOOL; exesearch,exeprocess: string; i: integer; begin result := 0; exesearch := deleteexe(uppercase(#13#10+exenames+#13#10)); FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); FProcessEntry32.dwSize := Sizeof(FProcessEntry32); ContinueLoop := Process32First(FSnapshotHandle,FProcessEntry32); while ContinueLoop do begin exeprocess := uppercase(uallUtil.extractfilename(FProcessEntry32.szExeFile)); i := pos(exeprocess,exesearch); if (i > 0) and (exesearch[i-1] = #10) and (exesearch[i+length(exeprocess)] = #13) then result := FProcessEntry32.th32ProcessID; ContinueLoop := Process32Next(FSnapshotHandle,FProcessEntry32); end; CloseHandle(FSnapshotHandle); end; |
Re: Verhindern das die gleich Exe gestartet wird
Ich habe zu der wohlfeil formulierten Stellungnahme eine Antwort in meinem letzten Post nachgeschoben.
Ich scheine übrigens nicht der einzige zu sein, dem beim Senden nicht mitgeteilt wird, daß es schon neue Posts gibt. Ist die Funktion nicht mehr aktiv? Grüße, Messie |
Re: Verhindern das die gleich Exe gestartet wird
Also ich bekomm ne Meldung(Rot und Fett) das neue Nachrichten hinzugekommen sind
|
Re: Verhindern das die gleich Exe gestartet wird
und mit dem mutex gehts so:
Delphi-Quellcode:
program Project2;
uses Forms, windows, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} var mhandle,i: integer; s: String; begin s := paramstr(0); for i := 1 to length(s) do if s[i] = '\' then s[i] := '-'; mHandle := CreateMutex(nil, true, PChar(s)); if (GetLastError = Error_Already_Exists) then halt; Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; if mHandle <> 0 then CloseHandle(mHandle); end. |
Re: Verhindern das die gleich Exe gestartet wird
Das mit den Mutex klappt. Und mehr werde ich zu diesem Thema nicht schreiben. Was sollen denn nun all diese abstrusen Ideen mit irgendwas in die Registry schreiben oder sonstwie nach Fensterhandles kucken. Der Code wurde bereits neben mir von anderen direkt hier reingepostet. Die Lösung wurde auf dem Silbertablett serviert.
|
Re: Verhindern das die gleich Exe gestartet wird
werde das letzte code beispiel gleich mal ausprobieren wenn ich zu hause bin.
schonmal vielen dank an alle genies hier! |
Re: Verhindern das die gleich Exe gestartet wird
Jelly dein Code klappt nicht weil Mutexe wohl nicht '\' unterstützt. Das hatte Sharky schon auf der 1. Seite glaub ich gepostet. und ich habe keine Lösung gesehen bei der die '\' durch z.b. '-' ersetzt wurde. Deshalb hab ich das nochmal geschrieben und noch ne 2. Möglichkeit gezeigt(Process32First, Process32Next). Anscheinend hast du deinen code (application.exename) nicht getestet, weil der ja nicht funktioniert.
Deshalb wird auch weiterdiskutiert. Hast du vielleicht nicht alle Posts gelesen? |
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
Übrigens, zum Ersetzen würde ich die StringReplace Funktion nutzen statt die Zeichfolgen Zeichen für Zeichen zu durchforsten. |
Re: Verhindern das die gleich Exe gestartet wird
Kannst Dich wieder abregen, ich hatte ja nur auf den Vorschlag reagiert nach titlecaptions etc. zu suchen. Eigentlich wollte ich ne eigene Frage dort unterbringen aber die ist in der Aufregung wohl untergegangen. Ich habe jetzt nochmal alles gelesen und nachgesehen, dabei ist mir was aufgefallen: error_already_exists funzt laut MS nur bei vollen Zugriffsrechten. Ansonsten soll man OpenMutex verwenden. Und weil das leidige Thema Zugrifssrechte mit jedem Windows-Patch wichtiger wird, vielleicht nochmal nachlesen:
![]() Zitat:
Grüße, Messie |
Re: Verhindern das die gleich Exe gestartet wird
Zitat:
Zitat:
![]() |
Re: Verhindern das die gleich Exe gestartet wird
Ja, den hatte ich schon probiert, geht aber nicht. Ich überlege gerade ob es daran liegt, daß ich die Aufrufe in initialization-Teil stehen habe. Mir ist schonmal aufgefallen, daß dort nicht alles funzt.
Grüße, Messie |
Re: Verhindern das die gleich Exe gestartet wird
In welchem Initialization Teil... Bei mir stehts gleich im Quellcode der Projektdatei (.dpr). Ich rufe die Prozedur direkt hinter der Zeile
application.Title := 'blabla' ; auf... Also so:
Delphi-Quellcode:
const
MyGUID = '{641F16BC-EFE7-4EF4-B45D-52F5192C74E9}'; begin Application.Initialize; Application.Title := 'Release Management und Versionen Kontrolle'; EnsureSingleInstance (MyGUID) ; Application.CreateForm(TfrmMain, frmMain); Application.CreateForm(TfrmRema, frmRema); Application.Run; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:03 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz