![]() |
Ende von MDI-Anwendungen erfahren
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:
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.
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); 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 |
Re: Ende von MDI-Anwendungen erfahren
Zitat:
Grüsse, Dirk |
Re: Ende von MDI-Anwendungen erfahren
Danke für die schnelle Antwort.
Zitat:
Ich würde es nach Deiner Antwort so machen:
Delphi-Quellcode:
Das Problem ist dabei aber die lang andauernde Schleife. Das soll nicht so Resourcen schonend sein.
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; Gruß, Alex |
Re: Ende von MDI-Anwendungen erfahren
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.
|
Re: Ende von MDI-Anwendungen erfahren
Danke für den Tipp!
Zitat:
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:
Gruß, Alex
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; |
Re: Ende von MDI-Anwendungen erfahren
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; |
Re: Ende von MDI-Anwendungen erfahren
Zitat:
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:
|
Re: Ende von MDI-Anwendungen erfahren
Wahrscheinlich nerve ich schon, aber schon das Prüfen auf Exklusivität führt nicht zum Ziel:
Ich benutze überwiegend ![]() 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? :wall: Gruß, Alex |
Re: Ende von MDI-Anwendungen erfahren
Ich werde mittelfristig bei einem Projekt auf das selbe Problem stossen und suche jetzt schon mal nach Lösungen :-D
Dabei bin ich bis jetzt auf folgenden Lösungsansatz gestossen: ![]() 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 :dancer2: |
Re: Ende von MDI-Anwendungen erfahren
Zitat:
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:33 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