Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Prozedur weiterleiten (https://www.delphipraxis.net/156974-prozedur-weiterleiten.html)

TheMiller 22. Dez 2010 18:10

Prozedur weiterleiten
 
Hallo,

ich weiß, dass dieser Topic-Titel sau dämlich ist, aber ich habe keine Ahnung, wie ich das gewünschte Verhalten anders bezeichnen könnte.

Problem ist folgendes: Ich habe eine Update-Klasse, die mehrere Programme von mir updatet. Sie wird einfach eingebunden und ein Thread sucht dann bei Start nach Updates für das entsprechende Programm. Wird eins gefunden, wird gefragt, ob der User das Update durchführen möchte. Sagt er "ja" (bzw. klickt auf "ja"), das Programm beendet sich und der Updater wird aufgerufen.

Im letzten Schritt liegt das Problem. Ich sende nach der Antwort mit "Ja" aus der Update-Klasse eine WM_QUIT-Message an das Programm, damit es geschlossen wird. Wenn jetzt das Programm allerdings einen "Wirklich-beenden"-Dialog eingebaut hat, wird das Programm nicht beendet, sondern diese Frage erscheint, der Updater öffnet sich dennoch, zieht das Update und versucht die Datei zu ersetzen.

Meine Lösung wäre nun folgende:
Ich habe in der Update-Klasse eine Property, welche mit einer Prozedur einer anderen Klasse (hier TForm) verknüpft wird. Wenn eine solche Prozedur verknüpft ist, wird diese aufgerufen und danach die WM_Quit gesendet. Die Prozedur würde eine Boolean-Variable setzen, welche den "Wirklich-beenden"-Dialog aushebelt.

Wie könnte ich das umsetzen? Oder habt ihr andere/bessere Ideen?

Danke im Voraus!

Hobby-Programmierer 22. Dez 2010 18:25

AW: Prozedur weiterleiten
 
Nabend ...,
vielleicht sollte dein Updater überprüfen ob der zu beendende Prozess noch aktiv ist und erst dann das Update einspielen, oder wie schon öfter beschrieben ... die laufende Instanz umbenennen und zeitgleich das Update einspielen. Bei Dll's bin ich mir aber net sicher ob das so funktioniert!

Uwe Raabe 22. Dez 2010 18:27

AW: Prozedur weiterleiten
 
Altermativ kannst du ja auch WM_ENDSESSION senden. Darauf sollte sich jede Anwendung ohne weitere Rückfragen selbst beenden.

Hobby-Programmierer 22. Dez 2010 18:36

AW: Prozedur weiterleiten
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1070010)
Altermativ kannst du ja auch WM_ENDSESSION senden. Darauf sollte sich jede Anwendung ohne weitere Rückfragen selbst beenden.

Was ist wenn noch Daten gespeichert oder zum Abschluss Benutzerhandlungen durchgeführt werden müssen?
Alternativ habe ich bei einigen Programmen beobachtet das Updates erst nach Programmende eingespielt werden.
Programmstart: auf Updates prüfen -> Updates runterladen -> normaler Programmablauf -> Programmende: Updates einspielen

Uwe Raabe 22. Dez 2010 19:16

AW: Prozedur weiterleiten
 
Zitat:

Zitat von Hobby-Programmierer (Beitrag 1070014)
Zitat:

Zitat von Uwe Raabe (Beitrag 1070010)
Altermativ kannst du ja auch WM_ENDSESSION senden. Darauf sollte sich jede Anwendung ohne weitere Rückfragen selbst beenden.

Was ist wenn noch Daten gespeichert oder zum Abschluss Benutzerhandlungen durchgeführt werden müssen?

Bei WM_ENDSESSION hast du keine Chance nachzufragen - das System fährt dann eigentlich nämlich runter (z.B. bei einem Stromausfall). Wenn die App sich nicht innerhalb eines Timeouts beendet wird sie gekillt. Leider reagieren längst nicht alle Programme korrekt auf diese Message. Aber seine eigenen Programme kann man ja ruhig darauf ausrichten.

Luckie 22. Dez 2010 20:08

AW: Prozedur weiterleiten
 
Ich halte das nicht für sehr günstig. Angenommen ich arbeite noch mit anderen Programmen, während das Update läuft. Dann wäre es mir nicht recht, wenn der Updater das System einfach runter fahren würde.

Uwe Raabe 22. Dez 2010 20:20

AW: Prozedur weiterleiten
 
Zitat:

Zitat von Luckie (Beitrag 1070037)
Ich halte das nicht für sehr günstig. Angenommen ich arbeite noch mit anderen Programmen, während das Update läuft. Dann wäre es mir nicht recht, wenn der Updater das System einfach runter fahren würde.

Ich habe ja nicht gesagt, daß er das System runterfahren soll. Er soll der App nur vorgaukeln, daß es runterfährt, damit sie sich ohne Nachfrage beendet. Das WM_ENDSESSION kommt ja nicht vom Betriebssystem.

Luckie 22. Dez 2010 20:57

AW: Prozedur weiterleiten
 
Kann man die Nachricht denn gezielt an ein Fenster senden?

Uwe Raabe 22. Dez 2010 21:05

AW: Prozedur weiterleiten
 
Zitat:

Zitat von Luckie (Beitrag 1070041)
Kann man die Nachricht denn gezielt an ein Fenster senden?

Na ja, wo wird er denn die WM_QUIT message hinschicken?

Luckie 22. Dez 2010 21:23

AW: Prozedur weiterleiten
 
Klar, die Nachricht kann man gezielt verschicken, aber kann man bei WM_ENDSESSION auch ein Fensterhandle angeben oder wird diese generell an alle Fenster verschickt? das war meine Frage.

Bummi 22. Dez 2010 21:49

AW: Prozedur weiterleiten
 
IMHO: Message ist Message
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  Canclose := False;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
   Sendmessage(Application.Handle,WM_Endsession,0,0)
end;

Luckie 22. Dez 2010 22:01

AW: Prozedur weiterleiten
 
Eben. Da man kein Zielfenster angeben kann, reagieren alle Fenster, die diese Nachricht behandeln auf die Nachricht und beenden sich.

Uwe Raabe 22. Dez 2010 22:59

AW: Prozedur weiterleiten
 
Zitat:

Zitat von Luckie (Beitrag 1070050)
Eben. Da man kein Zielfenster angeben kann, reagieren alle Fenster, die diese Nachricht behandeln auf die Nachricht und beenden sich.

Application.Handle ist doch das Zielfenster und TApplication behandelt WM_ENDSESSION. Natürlich sollen alle Fenster der anwendung von der Nachricht etwas mitbekommen, damit sie sich ordentlich beenden können. Das ist ja das Ziel dieser ganzen Aktion.

Andere Anwendungen bekommen aber von der Message nichts mit.

Bummi 22. Dez 2010 23:15

AW: Prozedur weiterleiten
 
Ich habe auf die Schnelle auch keinen Weg gefunden an das "Application"-Handle von z.B. Notepad zu kommen.
Ein Weg wäre auch:
Delphi-Quellcode:
Procedure TerminateProcessByClassname(ClassName:String);
//TW 2010
var
  hWindow, processHandle: hWnd;
  hprocessID: Integer;
begin
  hWindow := FindWindow(PWChar(ClassName), nil);
  if hWindow > 0 then
  begin
    GetWindowThreadProcessID(hWindow, @hprocessID);
    if hprocessID <> 0 then
    begin
      processHandle := OpenProcess
        (PROCESS_TERMINATE or PROCESS_QUERY_INFORMATION, False, hprocessID);
      if processHandle <> 0 then
      begin
        TerminateProcess(processHandle, 0);
        CloseHandle(processHandle);
      end;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    TerminateProcessByClassname('Notepad');
end;

Luckie 22. Dez 2010 23:44

AW: Prozedur weiterleiten
 
@Uwe: Also du schickst von dem Updater ein WM_ENDSESSION. da man diese Nachricht nicht gezielt an ein Fenster verschicken kann, bekommen alle Fenster diese Nachricht. Also auch mein Wordfenster in, dem ich gerade einen Brief schreibe. Dieses reagiert auch auf die Nachricht und beendet sich. Prima. Und was ist jetzt mit meinem Brief an dem ich gerade arbeite? Bestenfalls kommt noch ein Dialog, der mich zum Speichern auffordert. Aber nichts desto trotz, darf ich Woprd neu startet und alle andern Anwendungen, die ich auf hatte eventuell auch. Und das findest du in Ordnung? Kann ich mir nicht vorstellen.

Bummi 23. Dez 2010 00:13

AW: Prozedur weiterleiten
 
@Luckie

Wenn Uwe das Handle der jeweiligen Application hat funktioniert es genau so wie es gewünscht ist. Ich weiß nur noch nicht wie er an das Handle kommt.

Luckie 23. Dez 2010 00:24

AW: Prozedur weiterleiten
 
Mit FindWindow?

Bummi 23. Dez 2010 00:48

AW: Prozedur weiterleiten
 
Ich habe versucht mich durchzuhangeln...
Findwindow findet mein Mainform, wenn ich
Sendmessage(fHandle,WM_Endsession,0,0) mit den Handle des Mainforms abschicke passiert nichts, ich müsste bei Delphi zumindest an das Application.handle kommen, dort wird die Message richtig verarbeitet.
Ein Aufruf an das Fensterhandle von Notepad funktioniert ebenfalls nicht, ich habe versucht über die ProcessId ein gültiges Handle zu ergattern, bis jetzt Fehlanzeige.

Sir Rufo 23. Dez 2010 00:56

AW: Prozedur weiterleiten
 
Um mal wieder auf die Ausgangsfrage zurückzukommen ;)

Wozu überhaupt mit WM_QUIT oder sonstigen Nachrichten arbeiten?
Die Klasse ist doch direkt im Programm eingebunden ...

Baue in jedes deiner Programme eine Funktion ein, mit der die Anwendung beendet werden kann.

Diese Funktion übergibst du dann der Klasse und die Klasse ruft einfach diese Funktion auf, fertig.

Delphi-Quellcode:
Unit UpdateKlasse;

interface

type
  TQuitFunc = function : boolean;

  TUpdateKlasse = class
  ...
    Property QuitFunc : TQuitFunc Read FQuitFunc Write FQuitFunc;
 ...
  end;

...

procedure TUpdateClass.UpdateExecute;
begin
  if Assigned( FQuitFunc ) then
    if FQuitFunc then
      RunUpdateProg;
end;

Bummi 23. Dez 2010 00:59

AW: Prozedur weiterleiten
 
Zitat:

Die Klasse ist doch direkt im Programm eingebunden ...
:wall:
bitte alles vergessen was ich geschrieben habe...

Sir Rufo 23. Dez 2010 01:13

AW: Prozedur weiterleiten
 
Noch geschickter wäre es ja auch, das Beenden der Anwendung immer noch in die Hände des Users zu legen.

Das Update-Programm wird dann gestartet, wenn die Anwendung wirklich beendet wird:
Delphi-Quellcode:
program MeinProg;

uses
 ...
  UpdateKlasse;

begin
  ...
  if UpdateKlasse.UpdatesPending then
    UpdateKlasse.RunUpdateProg;
end.
Ob das Programm nun über die CallBack-Funktion wirklich beendet wird, oder der User zunächst noch etwas arbeiten möchte ist dabei dann egal. Beim Beenden (und vorhandenem Update) wird das UpdateProgramm gestartet.

Wichtig wäre es natürlich noch zu prüfen, ob die Anwendung mehrfach gestartet wurde.

Hobby-Programmierer 23. Dez 2010 01:40

AW: Prozedur weiterleiten
 
Zitat:

Zitat von Sir Rufo (Beitrag 1070072)
Noch geschickter wäre es ja auch, das Beenden der Anwendung immer noch in die Hände des Users zu legen.

:thumb:
Könnte man ja auch so wie Windows selbst bei Updates machen. User wird aufgefordert Windows neu gestartet - User entscheidet wann er dies tut und wird nur gelegentlich an das Vorhaben des Updates erinnert. Finde ich pers. als den besten Weg.

generic 23. Dez 2010 01:42

AW: Prozedur weiterleiten
 
Warum lässt du nicht den Benutzer die Programme beenden?

Wenn der Updater das Update durchführen will, dann zeigst du den User einen Dialog mit den noch geöffneten Programmen, welche geschlossen werden müssen.
Wenn er die nicht schließen will, startest du einfach das Update nach einen Reboot.

Mal abgesehen davon, wann und wie holst du die Adminrechte für die Installation der Updates?
Kann überhaupt jeder User updaten (hat jeder Adminrechte)?

Sir Rufo 23. Dez 2010 01:51

AW: Prozedur weiterleiten
 
Obwohl das ja eine Funktionalität des Setup-Programms ist.

Hier werden dann die Dateien kopiert obwohl diese in Benutzung sind und beim nächsten Neustart werden die dann auch tatsächlich kopiert.

Ist eine Möglichkeit, aber mich nervt es immer, wenn wegen einem Update der Rechner wieder neu gestartet werden muss.
Und wenn der Grund dafür nur darin liegt, weil ich das Programm noch geöffnet habe, dann doch fertig arbeiten lassen und beim Beenden updaten und nix mit Neustart.

Wer es dann sofort aktuell haben möchte, macht eben das Programm zu und wieder offen (nach dem Update).
Wer nicht, der macht das dann eben irgendwann ...

@generic

Wieso nach einem Reboot, direkt dann wenn die letzte Instanz der Anwendung geschlossen wird.

Adminrechte ... ja, das ist aber eine ganz neue Baustelle ;)
und es scheint bei ihm ja so zu funktionieren ... nur das Beenden der Anwendung war ja noch nicht ganz rund.

Richtig schick wird es ja, wenn die Installation via einem Dienst ablaufen würde (so wie bei MS) und alle eigenen Programme registrieren sich bei dem Update-Dienst.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 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 by Thomas Breitkreuz