AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Ende von MDI-Anwendungen erfahren
Thema durchsuchen
Ansicht
Themen-Optionen

Ende von MDI-Anwendungen erfahren

Ein Thema von Schwedenbitter · begonnen am 26. Sep 2009 · letzter Beitrag vom 3. Okt 2009
Antwort Antwort
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Ende von MDI-Anwendungen erfahren

  Alt 26. Sep 2009, 23:43
Hallo,

ich starte aus meinem Programm heraus über den einfachen Auruf bestimmter Dateien die damit verknüpften Programm. Z.B. öffnet mir ein Aufruf der Datei "Test.odt" diese Datei mit dem SWriter von OpenOffice. Da ich diese Datei aus bestimmten Gründen zuvor in ein temporäres Verzeichnis kopiere und von dort aus aufrufe/öffne, muss sie natürlich nach der Bearbeitung durch den SWriter wieder zurück kopiert werden. Das ganze geschieht (im Moment) so:
Delphi-Quellcode:
Procedure ExecuteProgramm(Const PFileName,Params: String; Warten: Boolean = True);
Var
   SEInfo      : TShellExecuteInfo;
   ExecuteFile   : String;
Begin
   ExecuteFile:='"'+PFileName+'"';
   FillChar(SEInfo,SizeOf(SEInfo),0);
   SEInfo.cbSize:=SizeOf(TShellExecuteInfo);
   With SEInfo Do
   Begin
      fMask:=         SEE_MASK_NOCLOSEPROCESS;
      Wnd:=            Application.Handle;
      lpFile:=         PChar(ExecuteFile);
      lpParameters:=   PChar(Params);
      nShow:=         SW_SHOWNORMAL;
   End;
   If ShellExecuteEx(@SEInfo) Then
      If Warten Then
         While Not Application.Terminated And
            (MsgWaitForMultipleObjects(1,SEInfo.hProcess,False,INFINITE,QS_ALLINPUT)=WAIT_OBJECT_0+1) Do
               Application.ProcessMessages;
End;

[...]

Procedure TForm1.Irgendwas;
Begin
   ExecuteProgramm('D:\Test.odt','',True);
Handelt es sich um eine SDI-Anwendung ist das ja kein Problem, da die Awendung fast immer beendet wird, wenn das Dokument geschlossen wird. Ich weiß, es gibt Ausnahmen, was aber nicht diskutiert werden soll. Bei MDI-Anwendungen läuft es so leider nicht.

So habe ich das Problem, dass der Benutzer z.B. die Test.odt über mein Programm lädt und ich warte. Danach öffnet er eine andere Datei, ohne den SWriter zu beenden. Selbst wenn er die Test.odt schließt, bekomme ich das nicht mit und warte weiter (auf das Ende vom SWriter). Am Ende kann das dazu führen, dass auch immer mehr Instanzen von meinem Programm im Speicher rumlungern. Schlimmer ist aber, dass die Dateien von mehreren Nutzern bearbeitet werden. Die aktuelle Datei steht dann nicht allen zur Verfügung.
Ich hoffe, Ihr könnte mein Problem nachvollziehen. Ansonsten bitte fragen.

Kann mir da jemand helfen?

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#2

Re: Ende von MDI-Anwendungen erfahren

  Alt 26. Sep 2009, 23:52
Zitat von Schwedenbitter:
Selbst wenn er die Test.odt schließt, bekomme ich das nicht mit und warte weiter
Warte doch darauf das Du Test.odt wieder exklusiv öffnen kannst.

Grüsse, Dirk
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Ende von MDI-Anwendungen erfahren

  Alt 27. Sep 2009, 00:14
Danke für die schnelle Antwort.
Zitat von Tryer:
Warte doch darauf das Du Test.odt wieder exklusiv öffnen kannst.
Kannst Du das bitte etwas konkreter ausführen und/oder mir ggf. Quellcode bzw. Links zukommen lassen?

Ich würde es nach Deiner Antwort so machen:
Delphi-Quellcode:
Function OpenExclusive(FName: String): Boolean;
Var
   F         : File;
Begin
   AssignFile(F, FName);
   FileMode:=fmShareExclusive;
   {$I-}
   Reset(F);
   CloseFile(F);
   {$I+}
   Result:=(IOResult=0);
End;


procedure TForm1.FormCreate(Sender: TObject);
begin
   Repeat
      Application.ProcessMessages;
   Until OpenExclusive('D:\Test.odt');
   ShowMessage('Jetzt isser fertig.');
end;
Das Problem ist dabei aber die lang andauernde Schleife. Das soll nicht so Resourcen schonend sein.

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#4

Re: Ende von MDI-Anwendungen erfahren

  Alt 27. Sep 2009, 00:33
Das Ganze einfach in einen seperaten Thread auslagern der an Stelle von ProcessMessages für 500ms schläft und bei Erfolg einen Event auslöst. Statt AssignFile arbeite ich meist mit CreateFile(), aber das sollte keinen grossen Unterschied machen. Der Vorteil des schlafenden Threads ist das er währenddessen keine Prozessorzeit benötigt und die Anwendung bedienbar bleibt.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Ende von MDI-Anwendungen erfahren

  Alt 27. Sep 2009, 00:52
Danke für den Tipp!
Zitat von Tryer:
... bei Erfolg einen Event auslöst. ...
Wie mache ich so etwas? Habe schon die Suche bemüht. Aber da finde ich immer nur sehr spezielle, das mir nicht auf die Sprünge hilft.

Auch mit den Parametern von CreateFile() tue ich mich schwer. Ich habe (gerade wegen dwDesiredAccess etc.) mal in der Hilfe nachgesehen, aber nichts gefunden, was mich weiter bringt.
Das hier bringt mir als Fehlermeldung "Falscher Parameter":
Delphi-Quellcode:
Function OpenExclusive(FName: String): Boolean;
Var
   FHandle      : THandle;
Begin
   FHandle:=CreateFile(PChar(FName),
                       GENERIC_READ Or GENERIC_WRITE,      // dwDesiredAccess
                       OF_SHARE_EXCLUSIVE,               // dwShareMode
                       nil,                              // lpSecurityAttributes
                       OPEN_EXISTING,                     // dwCreationDisposition
                       0,
                       0);
   If FHandle=INVALID_HANDLE_VALUE Then
      ShowMessage(SysErrorMessage(GetLastError));

End;
Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Tryer

Registriert seit: 16. Aug 2003
200 Beiträge
 
#6

Re: Ende von MDI-Anwendungen erfahren

  Alt 27. Sep 2009, 01:11
ungeprüft als Denkanstoß:
Delphi-Quellcode:
TFileAccessibleEvent = procedure(const Filename: string) of object;

TMyThread = class(TThread)
private
  FFilename: string;
  FOnDone: TFileAccessibleEvent;
  procedure DoFileAccessible;
public
  constructor Create(const Filename: string, ReadyEvent: TFileAccessibleEvent);
..

procedure TMyThread.Create(const Filename: string, ReadyEvent: TFileAccessibleEvent);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FFilename := Filename;
  FOnDone := ReadyEvent;
  Resume;
end;

procedure DoFileAccessible;
begin
  if Assigned(FOnDone) then
    FOnDone(FFilename);
end;

procedure TMyThread.Execute;
var
  h: THandle;
begin
  repeat
    h := CreateFile(PChar(FFilename),
                       GENERIC_READ, // dwDesiredAccess ist eigentlich egal
                       0, // dwShareMode 0 = Exklusiv
                       nil,
                       OPEN_EXISTING,
                       0,
                       0);
    if h <> INVALID_HANDLE_VALUE then
    begin
      CloseHandle(h);
      Synchonize(DoDone);
      Terminate;
    end else
      if GetLastError = ERROR_SHARING_VIOLATION then
        Sleep(500) //warten lohnt sich noch
      else
        Terminate;
  until Terminated;
end;
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: Ende von MDI-Anwendungen erfahren

  Alt 1. Okt 2009, 14:59
Zitat von Tryer:
ungeprüft als Denkanstoß ...
Herzlichen Dank für den Denkanstoß! ich komme leider erst heute dazu, mich daran zu probieren.

Ich habe den Code etwas begradigt übernehmen können. Der Compiler meldet keine Fehler. Da ich trotzdem nicht weiß, wie ich damit umgehen soll, hier nun 2 (blöde?) Fragen dazu:
  • Wie rufe ich den Constructor Create auf?
    Wenn ich das richtig sehe, dann muss ich dazu im Hauptprogramm/-objekt eine Procedure anlegen, die ich als Parameter angebe und die dann nach dem Freigeben der Datei aufgerufen wird ... FileName ist ja klar. Aber mit dem Event tue ich mich sehr schwer.
  • Was mache ich während der Laufzeit des Thread?
    Ich habe leider vergessen zu erwähnen, dass das ganze als nonVCL laufen soll. Da der Thread im Hintergrund läuft, ist dann mein Programm schon fertig, beendet und der Thread landet im Nirvana, oder?
Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Ende von MDI-Anwendungen erfahren

  Alt 2. Okt 2009, 00:30
Wahrscheinlich nerve ich schon, aber schon das Prüfen auf Exklusivität führt nicht zum Ziel:

Ich benutze überwiegend OpenOffice. Die Prüfung, ob ein exklusives Öffnen möglich ist, klappt dort (möglicherweise ja auch woanders) leider nicht.
Ich habe bei meinen leider sehr umfangreichen Fehlersuchen herausgefunden, dass OpenOffice die Datei während der Bearbeitung zwar offen hält; so weit so gut. Vor dem Speichern von Änderungen wird die Datei aber vermutlich kurz geschlossen, dann wieder geöffnet und danach erst die Änderungen gespeichert.
Dass führt dann dazu, dass ich - auf der Lauer liegend - OpenOffice sprichwörtlich die Datei klaue, noch bevor die Änderungen gespeichert wurden. Da ich mein Programm nach dem Zurückkopieren aber beende, habe ich immer nur die alte Version und Änderungen gehen an mir vorüber. Aufgefallen ist mir das erst, als ich das Zurückspeichern davon abhängig machte, dass sie der Zeitstempel der Datei geändert haben muss. Die waren aber zu meiner Verwunderung immer gleich. Jetzt weiß ich warum.
Schlimmer noch: Wenn der Benutzer zwischendurch mal speichert, glaubt mein Programm wegen des geschildern Phänomens, es sei schon alles vorbei und beendet sich planmäßig.

Wie kann ich denn das nun noch verhindern?

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Alex O.

Registriert seit: 30. Apr 2007
8 Beiträge
 
Delphi 2010 Enterprise
 
#9

Re: Ende von MDI-Anwendungen erfahren

  Alt 3. Okt 2009, 10:01
Ich werde mittelfristig bei einem Projekt auf das selbe Problem stossen und suche jetzt schon mal nach Lösungen

Dabei bin ich bis jetzt auf folgenden Lösungsansatz gestossen:
klick

Damit sollte ermittelt werden können, ob die Datei noch in Benutzung ist - allerdings nur auf dem lokalen Rechner, damit sieht man natürlich nicht, ob auf die Datei über das Netzwerk zugegriffen wird. Ich glaube dass ist in diesem Fall aber auch nicht relevant.

Alternative:
verwenden der oben genannten Threadlösung, die allerdings erst einen Erfolg (Datei ist freigegeben) meldet, wenn die Datei 2x innerhalb einer bestimmten Zeit (sagen wir mal 250ms) erfolgreich exklusiv geöffnet werden konnte.
Ganz sauber ist das natürlich nicht, aber vielleicht funktionierts.

Wenn es klappt, würde ich mich über ein Feedback freuen, dann hab ich schon direkt eine Lösung für mein zukünftiges Problem
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: Ende von MDI-Anwendungen erfahren

  Alt 3. Okt 2009, 11:30
Zitat von Alex O.:
Dabei bin ich bis jetzt auf folgenden Lösungsansatz gestossen:
klick
1. Ich bin leider nicht in der Lage, aus dem Quellcode rauszusuchen, was ich für die Lösung meines Problems benutzen könnte. Habe mir das aber im Moment auch nur kurz angesehen. Die Alternative mit dem doppelten Öffnen ging mir auch schon einmal durch den Kopf. Was ist aber, wenn das BS - aus welchem Grund auch immer - mal 300 ms stockt. Man hat also einen nicht definierten, unerwünschten Zustand.
2. In meinem Fall wäre eine weitere Alternative mit FindWindow nach dem WindowHandle zu suchen. Denn im Moment schreibt OpenOffice den Dateinamen mit in den Fenstertitel rein. Bedenken: Da habe ich aber das Problem, was ich machen soll, wenn sich das mal ändert.
3. Im Moment "löse" ich das unsauber, indem ich in einer Schleife solange warte, bis die seit mindestens OpenOffice 3 angelegte Lock-Datei wieder weg ist. Aber Siehe hierzu meine Bedenken unter Nr.2.

Ich sehe nur leider für mich mit meinen bescheidenen Kenntnisses als Gelegenheitsprogrammierer im Moment keine Möglichkeit, das Problem zu lösen. Es tut mir also leid, wenn ich Dich Alex O. insweit enttäuschen muss. Für Dein Projekt wünsche ich Dir von Herzen Erfolg. Poste mal Deine Lösungsansätze, wenn es soweit ist.

Gruß, Alex
Alex Winzer
  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 14:15 Uhr.
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