Entwickler-Ecke

Windows API - Ist Programm schon gestartet worden, prüfen?


Biarchiv - Sa 26.06.04 20:40
Titel: Ist Programm schon gestartet worden, prüfen?
Hallo,

Suche eine einfache Möglichkeit um zu prüfen ob mein Program schon
einmal gestartet wurde.

Danke


Moderiert von user profile icontommie-lie: Topic aus Sonstiges verschoben am So 27.06.2004 um 12:58


raziel - Sa 26.06.04 20:58

Hi,
Da gibts nen kleinen Trick:
Vor dem Initialisieren der Form in der "Project.dpr" ein Mutex oder ein Semaphore erstellen und anschließend GetLastError abfragen. Leifert das ERROR_ALREADY_EXIST zurück, dann wurde das Prog schon mal gestart und du kannst die doppelt gestartet Instanz beenden.

raziel

//edit: Freigeben des Mutex/der Semaphore am Ende der Project.dpr nicht vergessen!


SebDE - Sa 26.06.04 21:23
Titel: Re: Ist Programm schon gestartet worden, prüfen?
Das macht man normalerweise mit einem mutex.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var mHandle: THandle;    // Mutexhandle 

initialization 
  mHandle := CreateMutex(nil,True,'ProgrammName oder was anderes zum wiedererkennen'); // Mutex Handles sind Global gelten also also auch für andere Anwendungen
  if GetLastError = ERROR_ALREADY_EXISTS then begin 
    ShowMessage('Programm läuft schon!'); 
    halt; // zum Beenden  des Programms
  end

finalization 
  if mHandle <> 0 then CloseHandle(mHandle); // den mutex wieder freigeben 
end.


end. soll darauf hinweisen, dass initialisation/finalisation am Ende der Unit stehen müssen ;)

Ehm es ist dabei auch zu bedenken, dass der mutex beim Absturz des Programms nicht wieder freigegeben wird. (Aber so ist halt die gängigste & vor allem einfachste Lösung :) )


Motzi - So 27.06.04 12:51
Titel: Re: Ist Programm schon gestartet worden, prüfen?
SebDE hat folgendes geschrieben:
Ehm es ist dabei auch zu bedenken, dass der mutex beim Absturz des Programms nicht wieder freigegeben wird. (Aber so ist halt die gängigste & vor allem einfachste Lösung :) )

Stimmt nicht ganz.. im Allgemeinen gibt Windows beim Beenden eines Programms (ganz egal wie das Prog beendet wurde) alle Kernel-Objekte frei. Nur unter Win9x kann es dabei mit Mutexen zu Problemen kommen. Deswegen sollte man auch lieber Semaphore-Objekte verwenden, denn mit denen haut das immer hin...


DelphiFreund - So 27.06.04 13:26

Was ist ein Mutex und ein Semaphore?


raziel - So 27.06.04 13:39

Das sind Kernel-Objekte die (eigentlich) dazu dienen, Threads zu synchronisieren.
Ein Mutex kann immer nur von einem Thread besessen werden. So kann verhindert werden, dass z.B. zwei Threads gleichzeitig einen Shared Data (gemeinsam genutzter Speicher-) Bereich zu beschreiben. Im Gegensatz zum Mutex, den ausschließlich ein Thread besitzen kann, kann ein Semaphore mehrere Besitzer haben. Dazu wird beim Erzeugen einer Semaphore eine Maximale Anzahl an Besitzeren übergeben. Jedesmal wenn ein Thread auf diese Semaphore zugreift, wird dieser Zähler dekrementiert (erniedrigt). Wenn er bei 0 ankommt, kann kein weiterer Thread darauf zugreifen. Gibt ein Thread sein Semaphore wieder frei wierd der Zähler wieder erhöht. Das mag dann nützlich sein, wenn Du z.B. Microsoft die Anzahl der Word-Fenster begrenzen will. Einfach jedes neue Word Fensterl eine bestimmte Semaphore erstellen lassen bisses nicht mehr weiter geht.
Quelle: Win32-SDK-Referenz

raziel

//edit: kleinere fehlerchen ausgebessert... :?


DelphiFreund - So 27.06.04 14:01

Und Semaphore werden genauso wie Mutex erstellt, oder?


raziel - So 27.06.04 14:08

naja halt bei Mutexen Suche im MSDN CREATEMUTEX anstelle von Suche im MSDN CREATESEMAPHORE... ;-)
Zur Syntax schau mal in die Win32-SDK-Referenz, die bei Delphi dabei ist!
> Start-Programme-Borland Delphi X-Hilfe-MS SDK-Hilfedateien-Win32-SDK-Referenz

raziel


DelphiFreund - So 01.08.04 15:16

Ich bekommen immer die Fehlermeldung: 'Undefinierter Bezeichner: CreateSemaphore'. Warum? Es muss irgendeine Kleinigkeit sein, die ich vergessen habe, aber ich komm nicht drauf. (Hab davon leider auch keine Ahnung).


raziel - So 01.08.04 15:23

Ist Windows in der uses liste? :roll:

raziel


DelphiFreund - So 01.08.04 16:54

Hier ist mal der Quelltext:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

const
  MyGUID = '{4EA7F9F9-CCE6-48AD-A6EF-C3079215C4A6}';
var
  Semaphore: THandle;
begin
  Semaphore := CreateSemaphore(nil,0,1,PCHAR(MyGUID));
  if (GetLastError() = ERROR_ALREADY_EXISTS) then begin
    closehandle(Semaphore);
 end else begin
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
 end;
end.


Ist noch nicht fertig


Christian S. - So 01.08.04 17:00

Hallo!

Wie Raziel bereits sagte: Die Unit "windows" muss eingebunden werden.

MfG
Peter


DelphiFreund - So 01.08.04 17:05

Reicht es nicht wenn sie in Unit1 eingebunden ist?


Christian S. - So 01.08.04 17:11

Hm. :gruebel: Komischerweise reicht das nicht. :?


MasterT - So 01.08.04 17:14

Nein das reicht nicht. Du musst ja auch bei jedem neuen Formular, ganz gleich ob du schon andere Formulare in deiner USES Liste hast, in diesem alle Units einbinden die du in dem Formular benutzt.

Gruß

MasterT


DelphiFreund - So 01.08.04 17:15

Wie kann ich eine Funktion in Unit1 for Form1.OnCreate ausführen?


Christian S. - So 01.08.04 17:20

Neue Frage -> Neuer Thread


Christian S. - So 01.08.04 17:23

MasterT hat folgendes geschrieben:
Nein das reicht nicht. Du musst ja auch bei jedem neuen Formular, ganz gleich ob du schon andere Formulare in deiner USES Liste hast, in diesem alle Units einbinden die du in dem Formular benutzt.
Ich sollte mal wieder ausschlafen ... :-(


MasterT - So 01.08.04 18:20

garnicht!

@PeterLustig: Hab ich was verpasst?

Edit die 3te :)
Ahh habs gesehen. ^^