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 [Unit für Delphi >= 2010] Eigene Anwendung neu starten (https://www.delphipraxis.net/162066-%5Bunit-fuer-delphi-%3D-2010%5D-eigene-anwendung-neu-starten.html)

Björn Ole 4. Aug 2011 13:24

[Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Huhu,

ich möchte hier mal eine Unit zur Verfügung stellen, die das Neustarten der eigenen Anwendung sehr leicht gestaltet. Als Nebeneffekt kann es auch nur maximal eine laufende Instanz der Anwendung geben.

Zuerst muss die Unit in die uses Liste der .dpr (Project -> View Source) am besten als erstes eingebunden werden. Danach sollte noch mittels Strg+Shift+G eine GUID erzeugt und mit der vorhandenen ersetzt werden. Anschließen muss die Unit zusätzlich noch dort eingebunden werden, wo die Restart Methode aufgerufen werden soll, also z.B. in der Unit1.pas.

Kleines Beispiel:

Die .dpr
Delphi-Quellcode:
program Project1;

uses
  // Unit einbinden \\
  uApplicationRestarter in 'uApplicationRestarter.pas',
  // Alle weiteren Units ... \\
  Forms,
  Unit1 in 'Unit1.pas' {Form1} ,

{$R *.res}

begin
  // Diese zwei Zeilen einfügen und GUID abändern. \\
  if not TApplicationRestarter.Initialize(Application.Handle, '{33EB3B5C-9A2C-4E85-805C-FFD49C1AD468A}') then
    Exit;
  // Ab hier gehts normal weiter \\

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;

end.
Will man neu starten, dann einfach so:
Delphi-Quellcode:
uses uApplicationRestarter;

{...}

procedure TForm1.Button1Click(Sender: TObject);
begin
  TApplicationRestarter.Restart;
end;
Restart() gibt einen Boolean zurück, bei False kann man mittels GetLastError mit dem genauen Fehlergrund weiterarbeiten. Das Ganze geht leider erst ab Delphi 2010. Die Unit hab ich unter XE geschrieben und getestet, sollte aber auch unter 2010 laufen. Werde ich in den kommenden Tagen testen.

Für Verbesserungsvorschläge wär ich sehr dankbar. :thumb:

chaosben 4. Aug 2011 14:09

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Danke fürs Teilen. :)

Ich persönlich würde folgende Vorgehensweise für "schöner" befinden: Der Restarter ist ein class helper für TApplication und initialisiert sich selbst über die init-Routine der Unit.
Das hätte den Vorteil, das sich der "Aufwand" auf das Einbinden der Unit beschränkt und es ganz easy per
Delphi-Quellcode:
Application.Restart
nutzbar wäre.
Außerdem könnten dann auch User mit Delphis unter 2010 darüber freuen.

CCRDude 4. Aug 2011 14:11

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Hmmm... ok, ein paar hoffentlich konstruktive Vorschläge:

1. Warum "if ParamStr(1)=" und nicht "FindCmdLineSwitch()"?
2. Wenn bereits eine Instanz läuft, solltest Du die Parameter an diese weitergeben. Z.B. per Named Pipe.
3. Für Vista und später solltest Du eine Elevate-Möglichkeit einbauen (verb "runas" statt "open").
4. Auf Rechnern mit Terminal Services (also auch Fast User Switching) könntest Du Probleme haben. Gib dem Semaphor vllt. besser mal nen "Local\"-Prefix.

Björn Ole 6. Aug 2011 18:28

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Danke für die Vorschläge, ich arbeite mich mal durch:

Zitat:

Zitat von chaosben (Beitrag 1115063)
Der Restarter ist ein class helper für TApplication und initialisiert sich selbst über die init-Routine der Unit.

Vom Programmcode her schöner find ich das nicht, allerdings hast du Recht, ist besser wenn man die Unit auch mit älteren Delphi Versionen benutzen kann. Ich hab es mal geändert.

Zitat:

Zitat von chaosben (Beitrag 1115063)
Das hätte den Vorteil, das sich der "Aufwand" auf das Einbinden der Unit beschränkt

Die GUID muss allerdings immer noch irgendwo gesetzt werden, das wär ja unschön wenn man dafür in die Unit rein muss. Daher wird das Initialize wohl bleiben müssen.

Zitat:

Zitat von CCRDude (Beitrag 1115064)
1. Warum "if ParamStr(1)=" und nicht "FindCmdLineSwitch()"?

Die Funktion kannte ich noch gar nicht, danke, hab sie eingebaut.

Zitat:

Zitat von CCRDude (Beitrag 1115064)
2. Wenn bereits eine Instanz läuft, solltest Du die Parameter an diese weitergeben. Z.B. per Named Pipe.

Gute Idee, allerdings kommen mir Named Pipes dafür etwas zu umfangreich vor. Ich hab sie noch nie benutzt, von dem was ich lese scheint es mir aber etwas Overkill zu sein. Warum übergebe ich an ShellExecute nicht einfach
Delphi-Quellcode:
CmdLine + ' restart'
. Einwände?

Zitat:

Zitat von CCRDude (Beitrag 1115064)
3. Für Vista und später solltest Du eine Elevate-Möglichkeit einbauen (verb "runas" statt "open").

Verstehe nicht genau, was du meinst. open reicht doch alle Rechte weiter. Mit runas springt bei mir z.B. beim Neustart die UAC an, was ja nicht immer von Nöten ist.

Zitat:

Zitat von CCRDude (Beitrag 1115064)
4. Auf Rechnern mit Terminal Services (also auch Fast User Switching) könntest Du Probleme haben. Gib dem Semaphor vllt. besser mal nen "Local\"-Prefix.

Ist erledigt.

Für weitere Ideen bin ich immer dankbar. Werde noch etwas testen und dann bald die aktualisierte Unit posten.

chaosben 6. Aug 2011 22:30

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Warum muss es zwingend eine GUID sein? Per default würde es imho auch der Pfad zu Programm tun. Und für den Fall, das das nicht eindeutig genug ist, kann man ja noch eine GUID setzen. Denk ich. :-)

DeddyH 7. Aug 2011 10:52

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Verzeiht mir meine Unwissenheit, aber wann ist es eigentlich notwendig, dass sich eine Anwendung selbst neu starten muss? :gruebel:

EWeiss 7. Aug 2011 11:09

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
KA was du da machst aber das geht mit 1 Zeile.
Delphi-Quellcode:
ShellExecute(0, 'open', PWideChar(ParamStr(0)), nil, nil, SW_SHOW)


Noch einfacher geht es eigentlich nicht.
Und das sollte ab D1 funktionieren :)

Zitat:

aber wann ist es eigentlich notwendig, dass sich eine Anwendung selbst neu starten muss
Zum Beispiel bei mir wenn man seiner Anwendung Skins verpaßt hat.

gruss

WM_CLOSE 7. Aug 2011 11:18

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Zum Beispiel dann, wenn die Anwendung (aus welchem Grund auch immer) Admin-Rechte braucht.
Oder der Einfachheit halber, um die Initialisierung beim Programmstart nochmal zu durchlaufen, ohne große Änderungen am Code.
Oder bei einer unerwarteten Exception, bei der man nicht genau weiß was gerade schiefgelaufen ist (z.B. DB-Verbindung kaputt).
Oder wenn es ein Update der mitgelieferten DLLs gemacht hat und diese dann "sauber" neu laden soll.

Die letzten 3 treten bei einem sauber programmierten Programm so gut wie gar nicht auf, bei bestehendem Code vielleicht schon.

Björn Ole 7. Aug 2011 17:59

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Zitat:

Zitat von chaosben (Beitrag 1115426)
Warum muss es zwingend eine GUID sein? Per default würde es imho auch der Pfad zu Programm tun.

Hmpf, hast Recht. Hab den GUID Parameter entfernt und folgenden Namen gegeben:
Delphi-Quellcode:
semaphoreName := 'Local\' + StringReplace(ParamStr(0), '\', '/', [rfReplaceAll]);
Allerdings ist ein Editieren der .dpr immer noch notwendig, da ja der Programmstart u.U. abgebrochen werden muss. Oder kann ich das irgendwie sauber aus dem initialization Teil der Unit heraus machen?

Zitat:

Zitat von EWeiss (Beitrag 1115476)
KA was du da machst aber das geht mit 1 Zeile.
Delphi-Quellcode:
ShellExecute(0, 'open', PWideChar(ParamStr(0)), nil, nil, SW_SHOW)

Ja, so funktioniert es auch, allerdings kannst du so nicht garantieren, dass nur höchstens eine Instanz deiner Anwendung läuft. Das ist bei mir leider notwendig.

EWeiss 7. Aug 2011 18:46

AW: [Unit für Delphi >= 2010] Eigene Anwendung neu starten
 
Dann noch 3 zeilen dazu ;)

Delphi-Quellcode:
initialization
  hMutex := CreateMutex(nil, True, 'Meine Anwendung);
  if GetLastError = ERROR_ALREADY_EXISTS then
    Halt;

finalization
  if hMutex <> 0 then
    CloseHandle(hMutex)
Soll aber nicht heißen das deine Unit nicht das selbe macht.

gruss


Alle Zeitangaben in WEZ +2. Es ist jetzt 06:34 Uhr.
Seite 1 von 2  1 2   

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