AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Problem beim Programmneustart mit Instanzkontrolle
Thema durchsuchen
Ansicht
Themen-Optionen

Problem beim Programmneustart mit Instanzkontrolle

Ein Thema von Opa Knack · begonnen am 7. Nov 2013 · letzter Beitrag vom 10. Nov 2013
Antwort Antwort
Opa Knack

Registriert seit: 28. Dez 2004
Ort: Köln
166 Beiträge
 
#1

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 9. Nov 2013, 01:12
Danke für die hilfreichen Tipps, ich werde mich hineinknien. Übrigens funktioniert es mit
Delphi-Quellcode:
  // Nun ja ... wenn schon dann bitte mit Self
  {form1}Self.Close;
  // Da wir aber die Anwendung schließen wollen, müssen wir das HauptFormular schließen, also besser
  Application.MainForm.Close;

  // wozu das? unnötig!
  // application.ProcessMessages;

  // Hier jetzt das Handle vom Mutex freigeben
  CloseHandle( MyAppMutexHandle );

  // Nicht das Application.Handle übergeben sondern 0
  ShellExecute({Application.Handle} 0, 'open', Pchar(ParamStr(0)), nil, nil, sw_SHOWNORMAL);
nicht. Selbst wenn man MyAppMutexHandle (das logischerweise nicht vorhanden ist) durch den eigentlichen Mutex ersetzt.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 9. Nov 2013, 01:20
Danke für die hilfreichen Tipps, ich werde mich hineinknien. Übrigens funktioniert es mit
... nicht. Selbst wenn man MyAppMutexHandle (das logischerweise nicht vorhanden ist) durch den eigentlichen Mutex ersetzt.
Dann machst du irgendwas noch falsch, denn mit dem Freigeben des Mutex-Handle kann dieser Mutex wieder belegt werden.
(getestet)

Ähm, ja logisch ist das nicht bekannt - hätte ich besser schreiben sollen DatAppMutexDingensBumsHandleWatDuDaVerstecktInDerUnitRumliegenHast

Da du folgenden Code in deiner unit hast
Delphi-Quellcode:

if mHandle <> 0 then CloseHandle(mHandle)
gehe ich auch davon aus, dass du weißt wie man ein Handle freigibt und dass man dazu auch das Handle selber braucht
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 9. Nov 2013 um 01:25 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#3

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 9. Nov 2013, 09:53
...
Delphi-Quellcode:
...
  PreviousHandle := Windows.FindWindow(NIL,'MyProg'); //MyProg = Form1.caption
Das ist nicht allgemeingültig, denn viele Programme haben im Titel des Hauptformulars variable Informationen (z.B. den Namen der aktuell geladenen Datei, User- oder DB-infos etc.), d.h. Du weißt beim Programmstart nicht immer, was im Titel des Hauptformulars steht. Zudem musst Du deinen Code bei jeder Verwendung individuell anpassen.

Zum Thema 'eine Instanz und Neustart' wollte ich noch meinen Senf dazugeben:

Das Kürzeste, was ich diesbezüglich auf meinem Sperrmüll gefunden habe, ist eine Unit, die man einfach per 'uses' einbindet und dadurch einen Mehrfachstart verhindert.
Delphi-Quellcode:
unit OneInstance;
interface
implementation
uses Windows, SysUtils;

var
  hMutex: Cardinal;

initialization
  hMutex := CreateMutex(nil, True, PChar(UpperCase(ExtractFileName(ParamStr(0)))));
  if GetLastError = ERROR_ALREADY_EXISTS then Halt;
end.
Ich persönlich halte das für vollkommen ausreichend.

Mit 'Restart' wäre das diese Kleinstunit (Eben reingefrickelt):
Delphi-Quellcode:
unit OneInstance;
interface
Procedure Restart;
implementation
uses Windows, SysUtils, ShellApi;

var
  hMutex: Cardinal;

Procedure Restart;
Begin
  CloseHandle(hMutex);
  ShellExecute({Application.Handle} 0, 'open', Pchar(ParamStr(0)), nil, nil, sw_SHOWNORMAL);
  Halt; // Brutalstmögliches Beenden der eigenen Anwendung.
End;

initialization
  hMutex := CreateMutex(nil, True, PChar(UpperCase(ExtractFileName(ParamStr(0)))));
  if GetLastError = ERROR_ALREADY_EXISTS then Halt;
end.
Allerdings starten sich meine Programme nicht neu. Ich halte das für falsch. Ein Programm hat eine bestimmte Aufgabe und wenn es sie nicht erfüllen kann, dann soll sich das Programm beenden.

Wenn ich eine 24/7-Umgebung benötige, sorge ich (z.B. durch eine BAT-Datei), das die Anwendung neu gestartet wird.
Code:
:label
MyProg.exe
goto label
So kann ich einerseits die Anwendung in einer Endlosschleife am Leben halten, andererseits die gleiche Anwendung ohne Klimmzüge laufen lassen, bis sie abschmiert. Falls sie nun ständig abschmiert, kann ich die Endlosschleife einfach unterbrechen, indem ich die Batch-Datei beende (das Fenster schließe). Mit Selbstneustart benötige ich den Taskmanager, auf den ich aber auch nicht immer Zugriff habe.

Ich will nicht sagen, das das besser ist, aber es ist -für mich- so einfacher. In kritischen Umgebungen habe ich einen Sentinel, also eine Anwendung, die im Hintergrund bestimmte Prozesse überwacht und periodisch prüft, ob diese ansprechbar oder 'abgekackt' sind, d.h. hängen. Wenn ja, wird der Prozess gekillt und die Anwendung/Prozess neu gestartet. Eine zu überwachende Anwendung kann dem Sentinel auch sagen, das sie für immer sich beenden möchte, sodaß dieser die Überwachung einstellt.

So richtig hat mir das alles nie gefallen, denn eine Anwendung sollte immer laufen können. Leider geht das nicht immer (schlechte Treiber, externe DLL usw.)

Senfertig.
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#4

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 9. Nov 2013, 11:19
Ich habe mein DPR-File etwas geändert - vielleicht kann es jemand brauchen:

Delphi-Quellcode:
program MyProg;

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

{$R *.res}

procedure SwitchToThisWindow(h1: hWnd; x: bool); stdcall; external user32 Name
'SwitchToThisWindow'; {x = false: Size unchanged, x = true: normal size}

var
  hMutex: Cardinal;
  PreviousHandle : THandle;

BEGIN
  hMutex := CreateMutex(nil, True, PChar(UpperCase(ExtractFileName(ParamStr(0)))));
  if GetLastError = ERROR_ALREADY_EXISTS then
  begin
  PreviousHandle := Windows.FindWindow(NIL,PChar(UpperCase(ExtractFileName(ParamStr(0)))));
    if Windows.IsIconic(PreviousHandle) then
                Windows.ShowWindow(PreviousHandle, SW_RESTORE);
    SwitchToThisWindow(PreviousHandle, TRUE);
    SetForegroundWindow(PreviousHandle);
    SetWindowPos(PreviousHandle,
                HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW);
  end else
  begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end;
end.

Geändert von hathor ( 9. Nov 2013 um 18:18 Uhr)
  Mit Zitat antworten Zitat
musicman56
(Gast)

n/a Beiträge
 
#5

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 9. Nov 2013, 15:10
Hallo,

hMutex := CreateMutex(nil, True, PChar(UpperCase(ExtractFileName(ParamStr(0))))); wie ist das eigentlich, wenn ParamStr(0) Sonderzeichen wie "(" ")" "&", Leerzeichen usw. enthält. Funktioniert der Mutex dann noch richtig?

Was mir außerdem nicht ganz optimal erscheint ist die Tatsache, dass mit ParamStr(0) zwar verhindert wird, dass dieselbe Exe zeimal gestartet wird, aber nicht eine weitere Instanz desselben Programmes in einem anderen Ordner. Das zu verhindern kommt bei mir zumindest sehr häufig vor.

Es ist der Grund dafür, dass ich in meiner Unit zwei Möglichkeiten habe, den Mutex zu erzeugen: Einmal mit ParamStr(0) wenn mich dieser Sachverhalt nicht stört, und zusätzlich eine Funktion mit vorgegebenem Mutexnamen, den ich meistens von der Applikation ableite, zum Beispiel dem Application.Title.
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#6

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 9. Nov 2013, 19:35
Hallo,

hMutex := CreateMutex(nil, True, PChar(UpperCase(ExtractFileName(ParamStr(0))))); ...Was mir außerdem nicht ganz optimal erscheint ist die Tatsache, dass mit ParamStr(0) zwar verhindert wird, dass dieselbe Exe zeimal gestartet wird, aber nicht eine weitere Instanz desselben Programmes in einem anderen Ordner. Das zu verhindern kommt bei mir zumindest sehr häufig vor.
Label1.Caption:= UpperCase(ExtractFileName(ParamStr(0)));
ergibt NUR den Programm-Namen OHNE Pfad, deshalb kann das Programm nicht 2x gestartet werden.
  Mit Zitat antworten Zitat
musicman56
(Gast)

n/a Beiträge
 
#7

AW: Problem beim Programmneustart mit Instanzkontrolle

  Alt 10. Nov 2013, 13:04
Sorry, du hast natürlich recht. Das "UpperCase(ExtractFileName(..." habe ich übersehen.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:52 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