Delphi-PRAXiS
Seite 2 von 2     12   

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)

Fussball-Robby 6. Mai 2008 21:03

Re: Verhindern eine Anwendung mehrfach zu starten
 
Ich persönlich würde erst garnicht soweit gehen, die Dateigröße o.Ä. zu verwenden, es reicht doch eigentlich völlig aus, wenn man einen Inviduellen String benutzt (ok, der sollte jetzt nicht nur 1 Zeichen lang sein :lol: ). Ich glaube, da sind die Wahrscheinlichkeiten, dass ein anderes Programm einen Mutex anlegt, den Wert prüft und dann auch noch den gleichen Wert hat, schon relativ klein.

taaktaak 6. Mai 2008 21:10

Re: Verhindern eine Anwendung mehrfach zu starten
 
Ja, schätze ich auch so ein. Schön wäre es aber, wenn dieser individuelle String automatisch in der Unit erzeugt wird - die will ich ja einfach nur (ohne weitere Arbeit) in das Projekt einfügen....

// edit: Noch ein letztes Mal nachgedacht:
Das Umbenennen der Exedatei ist nur kritisch, wenn das Programm nach dem ersten Start umbenannt und unter neuem Namen erneut aufgerufen würde - nur dann greift der Test ins Leere. So viel Vorsatz sollte dann auch dadurch belohnt werden, das die zweite Instanz tatsächlich gestartet wird. Mein Fazit: Ich lasse meine Unit wie sie ist :wink:

OrNEC 11. Dez 2010 11:08

AW: Re: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von taaktaak (Beitrag 773011)
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.

Wie mache ich denn daraus eine Unit? Eine Datei Namens "rzM_OneInstanceOnly.pas" erstellen und in das Projektverzeichnis kopieren?

DeddyH 11. Dez 2010 14:41

AW: Verhindern eine Anwendung mehrfach zu starten
 
Ja sicher.

Carsten Hölscher 12. Jan 2022 18:40

AW: Verhindern eine Anwendung mehrfach zu starten
 
Ich wollte die hier https://www.delphipraxis.net/101-dop...erhindern.html angebotene Komponente in Delphi 11 nutzen, bekomme aber den Parameter beim 2. Start in der laufenden Instanz nicht korrekt, z.B. ist der 2. Teil des Parameter-Strings nur Salat. Ist sicherlich irgendein Unicode-Problem, das ich aber noch nicht durchdrungen habe. Hat zufällig schon mal jemand die Komponente auf den aktuellen Stand gebracht (oder hat Delphi evtl. inzwischen eine Hauslösung für das Thema, gefunden hab ich keine)?


Carsten

himitsu 12. Jan 2022 19:21

AW: Verhindern eine Anwendung mehrfach zu starten
 
Es lebe Unicode ... der Code war noch aus Zeiten von vor 2009 :stupid:

Hab's nicht getestet, aber ich denke mal so müsste es aussehn:

Delphi-Quellcode:
{ 604 OneInstance.pas }

          SetString(S, PChar(lpData), cbData div 2);

    cbData:= StrLen(lpData) * 2;
Delphi-Quellcode:
{ 149 OneInst.pas }

  cbData := cbData * 2;
  Result := GetMemory(cbData);
Bzw. wenn man es ganz genau nimmt, dann statt
Delphi-Quellcode:
2
besser ein
Delphi-Quellcode:
SizeOf(Char)
.

Aber 100% richtiger wäre es, wenn man den Code "richtig" fest auf UnicodeString/WideString, PWideChar und 2 umstellt, anstatt String, PChar und SizeOf(Char).

KodeZwerg 12. Jan 2022 19:52

AW: Verhindern eine Anwendung mehrfach zu starten
 
Falls das nicht funktioniert, ich nutze seit Ewigkeiten "PBOnceOnly" geschrieben von Dr. Peter Below, funktioniert bei mir tadellos.
Einfachmal nach "PBOnceOnly" hier oder per google suchen.
Ich habe leider nur noch eine von mir modifizierte Version, was ich modifizierte, abgesehen vom unit namen, habe ich aus dummheit nicht notiert aber es arbeitet tadellos mit Delphi Rio zusammen.

Delphi.Narium 12. Jan 2022 20:35

AW: Verhindern eine Anwendung mehrfach zu starten
 
PBOnceOnly.pas

Sinspin 13. Jan 2022 06:35

AW: Verhindern eine Anwendung mehrfach zu starten
 
Ich habe eine Lösung nur für Windows.
Verwende ich seit vielen Jahren in allen Programmen die es nötig haben.
Keine extra Unit, keine Komponente (wäre eh viel zu spät), keine Kopfschmerzen.

Das kommt direkt in die DPR:
Delphi-Quellcode:
// direkt nach begin
Mutex := CreateMutex(nil, True, 'EindeutigerName'); // das sollte am besten eine selbst erzeugte Class ID sein. Dann ist "eindeutig" recht sicher
if (Mutex <> 0) and (GetLastError = 0) then
  MutexError := false
else
  MutexError := true;
...
// alles was das programm so macht
...
// direkt vorm end
if Mutex <> 0 then
  CloseHandle(Mutex);
Natürlich sollte man den Mutex am Ende immer freigeben.
Aber zum Glück räumt auch Windows alles weg wenn der Prozess mal unerwartet übern Jordan geht.

Delphi.Narium 13. Jan 2022 11:22

AW: Verhindern eine Anwendung mehrfach zu starten
 
Das ist die einfachste Lösung, wenn man sicherstellen will, dass ein Programm nur einmal gestartet wird.

Was diese Lösung aber nicht kann:

Die übergebenen Parameter an die erste Instanz weiterreichen, damit diese damit weiterarbeiten kann.

Und genau da liegt ja aktuell das Problem.

HolgerX 13. Jan 2022 14:40

AW: Verhindern eine Anwendung mehrfach zu starten
 
Hmm..

Zitat:

Zitat von Delphi.Narium (Beitrag 1500530)
Das ist die einfachste Lösung, wenn man sicherstellen will, dass ein Programm nur einmal gestartet wird.

Was diese Lösung aber nicht kann:

Die übergebenen Parameter an die erste Instanz weiterreichen, damit diese damit weiterarbeiten kann.

Und genau da liegt ja aktuell das Problem.

Wieso sendest Du dann nicht eine Message an deine andere Instanz?

Z.B. in der DPR (wie oben als Beispiel)

Delphi-Quellcode:
const
  c_ProgStartMutexName = 'MeinProgrammName';



  {Attempt to create a named mutex}
  CreateMutex(nil, false, c_ProgStartMutexName);
  {if it failed then there is another instance}
  if GetLastError = ERROR_ALREADY_EXISTS then
    begin
    {Send all windows our custom message - only our other}
    {instance will recognise it}
    SendMessage(HWND_BROADCAST,
                RegisterWindowMessage(c_ProgStartMutexName),
                0,
                0);
    {Lets quit}
    Halt(0);
  end;
  Application.Initialize;

Dort, im Hauptfenster vorher:

Delphi-Quellcode:
const
  c_ProgStartMutexName = 'MeinProgrammName';

var
 OldWindowProc : Pointer; {Variable for the old windows proc}
 MyMsg  : Int64; {custom systemwide message}

function NewWindowProc(WindowHandle : hWnd;TheMessage  : LongInt;
  ParamW : LongInt; ParamL : LongInt) : LongInt stdcall;
begin
  if TheMessage = MyMsg then begin
    {Tell the application to restore, let it restore the form}
    SendMessage(Application.handle, WM_SYSCOMMAND, SC_RESTORE, 0);
    SetForegroundWindow(Application.Handle);
    {We handled the message - we are done}
    Result := 0;
    exit;
  end;
  {Call the original winproc}
  Result := CallWindowProc(OldWindowProc, WindowHandle, TheMessage, ParamW, ParamL);
end;

procedure TFormMeineMainForm.FormCreate(Sender: TObject);
begin
  //Register a custom windows message
  MyMsg := RegisterWindowMessage(c_ProgStartMutexName);
  //Set form1's windows proc to ours and remember the old window proc
  OldWindowProc := Pointer(SetWindowLong(FormHauptmenue.Handle, GWL_WNDPROC, LongInt(@NewWindowProc)));
  ..
end;

In diesem Beispiel wird der ersten Instanz einfach nur mitgeteilt, dass sie sich wieder nach vorne bringen soll..
Kannst aber auch eine andere Message oder IPC verwenden, um z.B. deinen Sting zu übergeben.

himitsu 13. Jan 2022 17:44

AW: Verhindern eine Anwendung mehrfach zu starten
 
Und wo übergibst du dort die "Parameter" ?

Die beiden verlinkten Units nutzen dafür WM_COPYDATA, um quasi GetCommandLine zu übergeben, wobei dort der Speicher für den "String" (damals ANSI und jetzt Unicode) falsch vewaltet wird/wurde, weswegen es nun nicht mehr im "neuen" Delphi funktioniert(e).



Man könnte es noch mit WM_SETTEXT/SendTextMessage versuchen, wo Windows notfalls die ANSI/Unicodeumwandlung vornehmen würde, falls nötig,
wenn man zu doof ungeschickt ist WM_COPYDATA richtig zu verwenden.

Sinspin 14. Jan 2022 07:06

AW: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1500530)
Das ist die einfachste Lösung, wenn man sicherstellen will, dass ein Programm nur einmal gestartet wird.

Was diese Lösung aber nicht kann:

Die übergebenen Parameter an die erste Instanz weiterreichen, damit diese damit weiterarbeiten kann.

Und genau da liegt ja aktuell das Problem.

Kalt erwischt :oops:
Danke.

Ich arbeite mit Named Pipes zur Kommunikation meiner Programteile untereinander. Das zuerst gestartete macht den Server auf, nach dem dann alle anderen Teile suchen.
Das gleiche geht doch hier auch.

Wobei natürlich PostMessage viel eleganter ist solange man an das passende Handle kommt.

Die Datenübertragung erledigt eine serealisierte Memtable deren Daten als Bytestrom oder B64 String übertragen werden.

HolgerX 14. Jan 2022 07:08

AW: Verhindern eine Anwendung mehrfach zu starten
 
Hmm..

Zitat:

Zitat von himitsu (Beitrag 1500563)
Und wo übergibst du dort die "Parameter" ?

Ich hatte doch geschrieben

Zitat:

Zitat von HolgerX (Beitrag 1500548)

In diesem Beispiel wird der ersten Instanz einfach nur mitgeteilt, dass sie sich wieder nach vorne bringen soll..
Kannst aber auch eine andere Message oder IPC verwenden, um z.B. deinen Sting zu übergeben.

Da hier zwei getrennte Prozesse involviert sind, muss natürlich eine Übermittlung über einen entsprechenden Weg gemacht werden..
Ich würde auch nicht einfach die Parameter als Text hinschicken, sondern ggf. eine Recordstrucktur, welche dem Empfänger auch mitteilt, dass es sich um 'Parameter des Programmaufrufes' handelt. ;)

HolgerX 14. Jan 2022 07:14

AW: Verhindern eine Anwendung mehrfach zu starten
 
Hmm..

Zitat:

Zitat von Sinspin (Beitrag 1500581)
Ich arbeite mit Named Pipes zur Kommunikation meienr Programteile untereinander. Das zuerst gestartete macht den Server auf, nach dem dann alle anderen Teile suchen.
Das gleiche geht doch hier auch.

Wenn schon eine Pipe da ist, wieso dann nicht statt Mutex auf das Vorhandensein der Pipe prüfen, schießlich kann eine NamedPipe nur einmal erstellt werden (soweit ich weiß), wie bei einem Socketserver.

Dann kannst Du die Informationen direkt dorthin schicken, ist sogar besser, da nicht alle Messages mit UserData Prozess übergreifend verschickt werden.

Ach ja:
Kein Postmessage, sondern Sendmessage verwenden! Denn z.B. WM_COPYDATA funktioniert nur richtig damit..

KodeZwerg 14. Jan 2022 09:33

AW: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1500508)

Jupp, genau das meinte ich. Ich hatte es lediglich um ein paar für mich speziellere Dinge erweitert wo ich mir gerade den Quelltext anschaue und vergleiche :-)
(ich wollte noch eine option haben die steuert ob programm a.exe parameter an b.exe übergibt, ob b.exe vor dem ".run" von a.exe terminiert werden soll usw... paar spielereien halt)
Wie dem auch sei, das rad muss nicht neu erfunden werden, soll nicht bedeuten das die Quelltexte der anderen falsch sind, um gottes willen nein, nur mach ich mir darüber keine gedanken mehr.
Lieber würde ich die PBOnceOnly.pas CrossPlatform fähig machen :-)

Carsten Hölscher 15. Jan 2022 17:16

AW: Verhindern eine Anwendung mehrfach zu starten
 
Zitat:

Zitat von himitsu (Beitrag 1500506)
Es lebe Unicode ... der Code war noch aus Zeiten von vor 2009 :stupid:

Hab's nicht getestet, aber ich denke mal so müsste es aussehn:

....

Ja, geht. Vielen Dank. Da war ich immerhin irgendwie schon ganz nah dran bei meinen eigenen Versuchen :-D

In dem Komponenten-Thema kann ich ja nicht schreiben, vielleicht kann es da jemand entsprechend aktualisieren?

Carsten


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr.
Seite 2 von 2     12   

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