Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Verhindern eine Anwendung mehrfach zu starten (https://www.delphipraxis.net/113334-verhindern-eine-anwendung-mehrfach-zu-starten.html)

Moony 6. Mai 2008 10:57


Verhindern eine Anwendung mehrfach zu starten
 
Hallo zusammen,

ich habe versucht mein Programm kein weiteres Mal aufrufen zu lassen, wenn es bereits einmal im System geöffnet ist. Das habe ich folgendermaßen probiert:

Delphi-Quellcode:
  doppelt := FindWindow('TApplication', PChar('meinProgramm'));
  if doppelt <> 0 then
  begin
     if IsIconic(doppelt) then
      ShowWindow(doppelt, SW_RESTORE)
    else SetForegroundWindow(doppelt);
  end
  else begin
    // Programmstart
  end;
aber leider funktioniert das bei der Anwendung nicht. Bei einer anderen schon. :gruebel:

Hoffe ihr könnt mir da weiterhelfen.

Gruß, Moony

Luckie 6. Mai 2008 11:02

Re: Verhindern eine Anwendung mehrfach zu starten
 
Na dann suchen wir doch einfach mal: Hier im Forum suchendoppelstart.

toms 6. Mai 2008 11:16

Re: Verhindern eine Anwendung mehrfach zu starten
 
Wird das Fenster gefunden, resp ist doppelt <> 0 ?

FAlter 6. Mai 2008 11:42

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hi,

ich hoffe mal du hast nicht einfach ohne zu überlegen nen Quelltext per Copy&Paste übernommen?

Falls doch: Check mal, ob dein Application.Title wirklich 'meinProgramm' ist. Bei mir funktioniert der Code.

Mfg
FAlter

SaFu 6. Mai 2008 11:46

Re: Verhindern eine Anwendung mehrfach zu starten
 
Schaumal von Luckie

http://www.delphipraxis.net/internal_redirect.php?t=136

Moony 6. Mai 2008 13:02

Re: Verhindern eine Anwendung mehrfach zu starten
 
@ toms:
doppelt ist immer <> 0. Egal ob die Anwendung bereits geöffnet ist oder nicht.

@FAlter:
Natürlich NICHT. Da steht der Title statisch drin, wie er bei den Optionen unter Application.Title angegeben ist.

@fuknersascha:
schaue ich mir eben an und probiere das aus.

FAlter 6. Mai 2008 13:07

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hi,

Zitat:

Zitat von Moony
@ toms:
doppelt ist immer <> 0. Egal ob die Anwendung bereits geöffnet ist oder nicht.

Also doch nicht nachgedacht. Er findet sich selbst. Du hast den Code an der falschen Stelle stehen ;) Es gehört nämlich in die DPR, und in den Else-Teil kommen die Application.XXX rein. Wobei das aus der Code-Lib sicherlich besser geeignet ist, denn der Code hier hat auch einige Schwachstellen.

Mfg
FAlter

Moony 6. Mai 2008 13:11

Re: Verhindern eine Anwendung mehrfach zu starten
 
Die Zeilen stehen in der *.dpr.

So, habe jetzt den Code con Luckie probiert und wenn ich die Anwendung zum zweiten Mal aufrufe, bekomme ich eine Exception. Ich habe jedoch diesen Code nicht als separate Unit angebunden, sondern meinen alten Source in der *.dpr ersetzt.

FAlter 6. Mai 2008 13:16

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hi,

Zitat:

Zitat von Moony
Die Zeilen stehen in der *.dpr.

Entweder gibt es ein anderes Programm, vermutlich auch mit Delphi (oder evtl. C++-Builder) geschrieben, was den gleichen Titel hat, oder du hast es doch an der falschen Stelle (bzw. die Application.XXX stehen VOR dem Code).

Delphi-Quellcode:
program Project1;

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

{$R *.res}


var
  Doppelt: THandle;
begin
  //Sicherstellen, dass zweiter Parameter Application.Title entspricht!
  //Delphi ärgert bei Verwendung einer Konstante.
  doppelt := FindWindow('TApplication', 'Test');
  if doppelt <> 0 then
  begin
     if IsIconic(doppelt) then
      ShowWindow(doppelt, SW_RESTORE)
    else
      SetForegroundWindow(doppelt);
  end
  else
  begin
    Application.Initialize;
    Application.Title := 'Test';
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end;
end.
Ich persönlich würde die Komponente aus der CodeLib nehmen, da steht was von Parameterübergabe dabei ;)

Mfg
FAlter

Moony 6. Mai 2008 13:19

Re: Verhindern eine Anwendung mehrfach zu starten
 
Noch mal: JA, es steht an der richtigen Stelle!!!!


In meinem anderen Programm funktioniert das ja.

SubData 6. Mai 2008 13:55

Re: Verhindern eine Anwendung mehrfach zu starten
 
Eine Alternative:

Delphi-Quellcode:
initialization
  hApp := CreateMutex(nil, True, 'APPNAME');
  if GetLastError = ERROR_ALREADY_EXISTS then
  begin
    MessageDlg('Das Programm kann nur einmal gestart werden!', mtError, [mbOK],0);
    Halt;
  end;

finalization
  if hApp <> 0 then CloseHandle(hApp);

Edit: Hab gerade gesehen, dass Luckie einen fast identischen Code bereits verlinkt hat.

SaFu 6. Mai 2008 13:58

Re: Verhindern eine Anwendung mehrfach zu starten
 
Also ich habe den Code von Luckie als unit eingebunden und der Funzt bei mir schon ewig ohne Probleme

Moony 6. Mai 2008 14:04

Re: Verhindern eine Anwendung mehrfach zu starten
 
Ich habe jetzt die Komponente von CalganX genommen. Aber irgendwie funktioniert das alles nicht so wie es soll....

@Subdata:
so habe ich es auch schon probiert, aber alles erfolglos. Ich bekomme jedesmal eine dicke Exception wenn ich die Applikation das zweite Mal starte.

@fuknersascha:
Ich habe jetzt nochmals den Code von Luckie 1:1 kopiert nur den Unitnamen umbenannt und ich bekomme beim zweiten Start des Applikation eine Exception.


Bei dieser Zeile:
Delphi-Quellcode:
mHandle := CreateMutex(nil,True,'meinProgrammtitel');
steht der Programmtitel statisch als String.

SaFu 6. Mai 2008 14:08

Re: Verhindern eine Anwendung mehrfach zu starten
 
Da muss dein Programmtitel rein also MeinProgramm.exe

Moony 6. Mai 2008 14:09

Re: Verhindern eine Anwendung mehrfach zu starten
 
Mit oder ohne Extention?

Luckie 6. Mai 2008 14:09

Re: Verhindern eine Anwendung mehrfach zu starten
 
Nein, da kann jede beliebige, eindeutige Zeichenfolge stehen. Am besten nimmt man eine GUID dafür.

Klaus01 6. Mai 2008 14:10

Re: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von Moony
Ich habe jetzt nochmals den Code von Luckie 1:1 kopiert nur den Unitnamen umbenannt und ich bekomme beim zweiten Start des Applikation eine Exception.


Delphi-Quellcode:
mHandle := CreateMutex(nil,True,'meinProgrammtitel');

Hallo,

bekommst Du die Exception auch, wenn Du die Applikation
nicht aus der IDE startest?

Grüße
Klaus

TeronG 6. Mai 2008 14:10

Re: Verhindern eine Anwendung mehrfach zu starten
 
Notfalls:
Bei LMD-Tools gibt es ein "OneInstance" ...
Entweder Downloaden (http://www.lmdinnovative.com/) oder auf der Partner-Software-CD von Borland gugn (da sollts auch druff sein)

Sharky 6. Mai 2008 14:11

Re: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von fuknersascha
Da muss dein Programmtitel rein also MeinProgramm.exe

Nich ganz. Dort muss ein eindeutiger String stehn. Am einfachsten eine GUI-ID

[EDIT]Da guckt man vor dem absenden mal schnell etwas nach; und was passiert? Luckie sendet 2 Minuten früher :cry:

SubData 6. Mai 2008 14:11

Re: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von fuknersascha
Da muss dein Programmtitel rein also MeinProgramm.exe

Beim Mutex kannst du "irgendeinen" String verwenden.
Wie Luckie bereits erwähnte, bietet sich eine GUID an.

Edit: Der Hai war schneller ;-)

SaFu 6. Mai 2008 14:13

Re: Verhindern eine Anwendung mehrfach zu starten
 
also ich habe es bei mir mit gemacht habe es nie anders versucht habe auch mit dem Code nie Probleme gehabt

Da kommt man ja mit dem schreiben garnet hinterher

BOH 6. Mai 2008 14:14

Re: Verhindern eine Anwendung mehrfach zu starten
 
Noch'n Tipp: Max Components: TmxOneInstance (Freeware)

Moony 6. Mai 2008 14:17

Re: Verhindern eine Anwendung mehrfach zu starten
 
@Klaus:
Die Exception kommt auch, wenn ich keinerlei Überprüfungen in die Applikation einbinde.

Und wo bekomme ich diese GUI-ID her?

Sharky 6. Mai 2008 14:18

Re: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von Moony
...Und wo bekomme ich diese GUI-ID her?

Einfach im Editor [STRG]-[Umschalten]-G drücken.

himitsu 6. Mai 2008 14:20

Re: Verhindern eine Anwendung mehrfach zu starten
 
PS: MD5 und GUID sind gleich groß ... also falls sich mal jemand eine GUID live berechnen will :angel:


Also wenn man möchte, daß eine bestimmte Datei (und nur die eine Dateiversion) nur einmal gestartet werden darf > MD5 aus sich selbst (eigene EXE) berechnen

Moony 6. Mai 2008 14:23

Re: Verhindern eine Anwendung mehrfach zu starten
 
So, habe das folgendermaßen gemacht:

Delphi-Quellcode:
unit Unit1;

interface

implementation

uses windows,Dialogs,sysutils;

var mHandle: THandle;   // Mutexhandle

Initialization
  mHandle := CreateMutex(nil,True,'{7A366489-37B0-4E63-81A0-F0BBC281614D}');
  // 'xxxxx' Der Anwendungsname ist hier einzutragen
  if GetLastError = ERROR_ALREADY_EXISTS then begin  
    // Anwendung läuft bereits
    {showMessage('Anwendung läuft bereits!!!!!');}   
    // Wenn du deine Meldung willst, mach die Klammern weg
    Halt;
  end;

finalization  // ... und Schluß
  if mHandle <> 0 then
    CloseHandle(mHandle)
end. {Dieter Hirt}
In der *.dpr selbst steht nichts drin, was eine vorherige Überprüfung durchführt. Weiterhin bekomme ich beim zwieten Start eine Exception. Blöd, dass man so etwas nicht debuggen kann...

FAlter 6. Mai 2008 14:27

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hi,

Zitat:

Zitat von Moony
Blöd, dass man so etwas nicht debuggen kann...

doch, kann man. Notfalls mit zweimal Delphi offen, aber es sollte reichen, das Programm das zweite Mal zu debuggen und das erste Mal ohne Debugger zu starten.

Mfg
FAlter

Moony 6. Mai 2008 14:40

Re: Verhindern eine Anwendung mehrfach zu starten
 
Also:
  • 1.
    Wenn man in den tausend anderen Units auch tausend andere Initialisierungen hat, dann MUSS man die Überprüfungsunit auch als aller erste Unit in der *.dpr in die uses aufnehmen. Dann funktioniert auch die Überprüfung ohne weitere Exceptions.

    2. Wenn die Anwendung bereits geöffnet ist, dann soll diese auch in den Vordergrund geholt werden. Ich habe das so versucht, aber ohne Erfolg:
    Delphi-Quellcode:
      mHandle := CreateMutex(nil,True,'{7A366489-37B0-4E63-81A0-F0BBC281614D}');
      if GetLastError = ERROR_ALREADY_EXISTS then
      begin
         if IsIconic(mHandle) then
          ShowWindow(mHandle, SW_RESTORE)
        else SetForegroundWindow(mHandle);
        Halt;
      end;

hoika 6. Mai 2008 14:41

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hallo,

benenne die Unit mal um.
Unit1 ist denkbar schlecht.

Und dann binde sie als erste unit in der dpr ein.


zu langsam ;(


schau dir mal das "In den Vordergrundbringen" hier an
1


Beitrag #14


Heiko

Moony 6. Mai 2008 15:14

Re: Verhindern eine Anwendung mehrfach zu starten
 
Klar, dass die Unit umbenannt wird. Wurde nur vorerst zum Test angelegt und gespeichert.

Habe mir die Funktion "EnsureSingleInstance" angeschaut. Theoretisch muß ich nicht die ganzen Überprüfungen machen. Was das eigentliche in dieser Funktion betrifft, führe ich ja bei mir aus. Sprich:
Delphi-Quellcode:
mHandle := CreateMutex(nil,True,'{7A366489-37B0-4E63-81A0-F0BBC281614D}');
...
SetForegroundWindow(mHandle);
BringWindowToTop(mHandle);
Aber leider wird das Programm immer noch nciht in den Vordergrund gesetzt.

Klaus01 6. Mai 2008 15:23

Re: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von Moony
Klar, dass die Unit umbenannt wird. Wurde nur vorerst zum Test angelegt und gespeichert.

Habe mir die Funktion "EnsureSingleInstance" angeschaut. Theoretisch muß ich nicht die ganzen Überprüfungen machen. Was das eigentliche in dieser Funktion betrifft, führe ich ja bei mir aus. Sprich:
Delphi-Quellcode:
mHandle := CreateMutex(nil,True,'{7A366489-37B0-4E63-81A0-F0BBC281614D}');
...
SetForegroundWindow(mHandle);
BringWindowToTop(mHandle);
Aber leider wird das Programm immer noch nciht in den Vordergrund gesetzt.

Hallo,

wenn man sich durchgelesen hat was createMutex macht,
dann versuchst Du wenn mHandle = Null ist die Aplikation mit dem
Handle in den Vordergrund zu setzen.
Solltest Du nicht das Handle der bereits laufenden Aplikation ermitteln
und diese dann in den Vordergrund setzten?

Zitat:

Zitat von msdn2
If the function succeeds, the return value is a handle to the newly created mutex object.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Grüße
Klaus

taaktaak 6. Mai 2008 15:34

Re: Verhindern eine Anwendung mehrfach zu starten
 
Moin, Moin,
vielleicht kann die Suche nach einer Lösung abgekürzt werden. Ich verwende seit Jahren mit Erfolg folgende Unit...

Delphi-Quellcode:
unit rzM_OneInstanceOnly;

// Unit lediglich in das Projekt aufnehmen, danach werden mehrere Instanzen
// des Programmes unterbunden; bei erneutem Aufruf wird automatisch die
// erste Instanz aktiviert.

interface { ----------------------------------------------------------------- }

implementation { ------------------------------------------------------------ }

uses Forms,SysUtils,Windows;

var Mutex : THandle;
     MName : String;
     h    : HWnd;

initialization { ------------------------------------------------------------ }

 MName:=ExtractFileName(ChangeFileExt(Application.ExeName,'_MTX'));
 Mutex:=CreateMutex(nil,true,pchar(MName)); // Mutex anlegen

 if GetLastError=ERROR_ALREADY_EXISTS then begin // Fehler, Pgm schon aktiv!

   h:=0; // vorhandene Instanz suchen
   repeat
     h:=Windows.FindWindowEx(0,h,PChar('TApplication'),PChar(Application.Title))
     until h<>Application.Handle;

   if h<>0 then begin // aktivieren
     Windows.ShowWindow(h,SW_Restore);
     Windows.SetForegroundWindow(h);
     end;

   halt; // und diesen zweiten Aufruf beenden!
   end;

finalization { -------------------------------------------------------------- }

  ReleaseMutex(Mutex); // Mutex der ersten Instanz wieder freigeben!

end.

Moony 6. Mai 2008 15:49

Re: Verhindern eine Anwendung mehrfach zu starten
 
@taaktaak:
Supi!!! Genau so funktioniert das auch.


Vielen Dank an alle, die ihre Zellen haben anstrengen müssen. Jetzt habe ich meinen Code so, wie ich es haben möchte.

Für alle, die es auch mal brauchen:
Delphi-Quellcode:
unit OneInstance;

interface

implementation

uses Windows, Forms;

var
  mHandle : THandle;   // Mutexhandle
  h      : HWnd;

initialization
  mHandle := CreateMutex(nil,True,'{7A366489-37B0-4E63-81A0-F0BBC281614D}');

  if GetLastError=ERROR_ALREADY_EXISTS then
  begin // Fehler, Pgm schon aktiv!
    h := 0; // vorhandene Instanz suchen
    repeat
      h := Windows.FindWindowEx(0,h,PChar('TApplication'),PChar(Application.Title))
    until h<>Application.Handle;

    if h<>0 then
    begin // aktivieren
      Windows.ShowWindow(h,SW_Restore);
      Windows.SetForegroundWindow(h);
    end;
    Halt; // und diesen zweiten Aufruf beenden!
  end;

finalization  // ... und Schluß
  if mHandle <> 0 then
    CloseHandle(mHandle)

end.

taaktaak 6. Mai 2008 20:29

Re: Verhindern eine Anwendung mehrfach zu starten
 
Moin, Moin.

Schön, dass es funktioniert. Allerdings halte ich das Fragment...

Delphi-Quellcode:
CreateMutex(nil,True,'{7A366489-37B0-4E63-81A0-F0BBC281614D}');
für suboptimal. Warum sollte man hier eine Konstante verwenden? Gibt es nicht ein Durcheinander, wenn zwei unterschiedliche Programme - die beide diese Konstante benutzen - auf diese Art und Weise ihe Vorhandensein prüfen?

Ist vielleicht eine etwas theoretische Situation, aber der Aufwand, statt der Konstanten den veränderten EXE-Namen zu verwenden, ist doch marginal - oder?

FAlter 6. Mai 2008 20:35

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hi,

den EXE-Namen würde ich nicht nehmen. Was, wenn zwei Programme gleich heißen? Und eine GUID ist fast ziemlich eindeutig, denn wenn der PC ne Netzwerkkarte hat, wird diese zur GUI-Erzeugung herangezogen, und die MAC sollte eindeutig sein. Und die Uhrzeit spielt auch mit rein. Du wirst wohl nicht zweimal gleichzeitig auf deinem PC ne GUID erstellen? Wenn du also für jedes Programm ne andere GUID nimmst. Kannst ja den EXE-Namen noch zusätzlich reinnehmen und meinetwegen die Zeichen {, - und } rausnehmen, wenn du Angst hast.

Mfg
FAlter

PS: Wie wird eine GUID berechnet, wenn der PC, auf dem sie drauf ist, keine Netzwerkkarte hat?

taaktaak 6. Mai 2008 20:40

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hallo Falter,
ein interesanter Aspekt! Zugegeben! Wir sind uns doch aber einig darüber, dass eine Konstante, unter der Voraussetzung, dass das ganze eine Unit ist, die bedarfsweise unverändert eingebunden wird, nicht sinnvoll ist?

//edit:
Noch 'mal nachgedacht! Ich halten dann die Kombination aus ExeName und Länge der Exedatei für ausreichend. Die Wahrscheinlichkeit, dass zwei unterschiedliche Programme die gleiche Länge haben UND einen Mutex anlegen, auf den geprüft wird, dann doch für sehr, sehr unwahrscheinlich - vielleicht gibt's hier ja einen Mathematiker, der die Wahrscheinlichkeit mal ausrechnen möchte?

FAlter 6. Mai 2008 20:52

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hi,

ja, bei unverändertem Übernehmen in ein anderes Projekt ist das sehr sinnlos. So gesehen kann ich nur zustimmen.

Mir persönlich gefällt übrigens das Delphi-Referenz durchsuchenhalt nicht.

Mfg
FAlter

Fussball-Robby 6. Mai 2008 20:55

Re: Verhindern eine Anwendung mehrfach zu starten
 
Application.Exename alleine scheint mir aber nicht "sicher", denn den Namen der Anwendung kann jeder zu jeder zeit ändern.

taaktaak 6. Mai 2008 20:55

Re: Verhindern eine Anwendung mehrfach zu starten
 
Jooo, sofort und abschließend überzeugt:
"Halt" fliegt 'raus und wird durch "Terminate" ersetzt - Danke!

taaktaak 6. Mai 2008 20:58

Re: Verhindern eine Anwendung mehrfach zu starten
 
Hmm, ist in gewisser Weise ein Argument. Obwohl das natürlich schon ein "Sabotage" der Software ist, die auch an anderen Stellen, die viel unangenehmere Auswirkungen haben können, auch Probleme schaffen könnte. Hmm, was ist denn dann die derzeit beste Lösung? Mit der GUID kann ich mich nicht so richtig anfreunden...


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:57 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz