![]() |
Komponente verursacht Fehler beim Beenden von Delphi/Projekt
Hallo und guten Tag an alle DP´ler,
Habe in meinem vorherigen Threat ![]() Und zwar läuft alles korrekt, wenn ich meine Komponente verwende (Unit mit Komponente startet, alles kann so wie vorgesehen verwendet werden und schließt ohne Fehlermeldung). Wenn jetzt aber das Projekt geschlossen wird, treten mehrere Fehler auf, bei denen ich eure Hilfe bräucht, weil ich damit gar nichts anfangen kann. Fehler beim Beenden von Delphi/ des Projektes: Projekt beenden 1.) ungöltige Zeigeroperation 2.) Zugriffsverletzung bei Adresse 2000679C in Modul rtl100.bpl. Fehler bei Adresse FFFFFFFF Delphi 3.) Fehlermeldung, die ich versenden kann (oder nicht) wegen schwerem Fehler beim Beenden von Delphi 4.) Exception EAccessViolation in Modul coreide100.bpl bei 0015EDC8.Zugriffsverletzung bei Adresse 20A8EDC8 in Modul coreide100.bpl. Lesen von Adresse 0000049C. Habe dazu nicht wirklich etwas gefunden, die meisten Threats bezugen sich lediglich auf Fehler, die beim Beenden des Programmes auftraten. Vieleicht kann mir jemand einen Hinweis geben, wo ich den Fehler suchen muss. Vielen Dank BAMatze Edit 1: Also die Fehler kann ich erstmal beseitigen, indem ich das Speichern
Delphi-Quellcode:
im Destructor weglasse. Wobei ich eigentlich ja Änderungen speichern möchte. Hat dort eventuell jemand eine Idee? Also wie ich trotzdem speichern kann?
FExcelWorkbook.Close(true);
|
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Hallo noch mal an alle DP´ler,
Ich pusche dieses Thema mal aus dem Grund, da vieleicht jemand mal in der SuFu darauf stößt und ähnliche Anlaufschwierigkeiten hat, wie ich. Also die Probleme sind beseitigt, dass Delphi/ das Projekt geschlossen werden kann ohne, dass es irgendeinen Fehler gibt. Ich gebe hier mal meinen Quellcode zum besten für ein Testprogramm (ist allerdings nicht uneigennützig, weil noch ein Problem besteht, bei dem ich ein wenig Hilfe brauche (ein Fehler besteht noch))
Delphi-Quellcode:
Wer diesen Quellcode ohne FastMM4 testet, wird kein Problem feststellen. Allerdings sind noch 2 Speicherlecks vorhanden, welche ich gern beseitigen würde und zwar beim Speichern. Das Speichern funktioniert allerdings. Wieso treten aber Speicherlecks auf?
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExcelXP; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private-Deklarationen } public { Public-Deklarationen } end; const Testname = 'Test.xls'; var Form1: TForm1; FExcelApplication: TExcelApplication; FExcelWorkbook: TExcelWorkbook; FExcelWorksheet: TExcelWorksheet; implementation {$R *.dfm} procedure ExcelDatenbank_anlegen; var sparentroot: string; iUserLCID: integer; begin sparentroot := ExtractFilePath(ParamStr(0)); iUserLCID := GetUserDefaultLCID; FExcelApplication := TExcelApplication.Create(Nil); FExcelApplication.Workbooks.Add(emptyparam, iUserLCID); FExcelWorkbook := TExcelWorkbook.create(Nil); FExcelWorkbook.ConnectTo(FExcelApplication.ActiveWorkbook as ExcelWorkbook); FExcelWorkbook.Worksheets.Add(emptyParam, emptyParam, emptyParam, emptyParam, iUserLCID); FExcelWorksheet := TExcelWorksheet.create(Nil); FExcelWorksheet.ConnectTo(FExcelWorkbook.ActiveSheet as ExcelWorksheet); FExcelWorksheet.Cells.Item[3,1] := 'Hallo'; FExcelWorksheet.Cells.Item[3,2] := 'dies'; FExcelWorksheet.Cells.Item[3,3] := 'ist'; FExcelWorksheet.Cells.Item[3,4] := 'ein'; FExcelWorksheet.Cells.Item[3,5] := 'Test'; FExcelWorkbook.Close(true, sparentroot + Testname, emptyParam, iUserLCID); // Speichert die Änderungen in Excel } //Speicherleck FExcelWorksheet.Free; FExcelWorkbook.Free; FExcelApplication.Free; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin if not (csDesigning in Self.ComponentState) then begin FExcelWorkbook.Close(true); // Speicherleck FExcelWorksheet.Free; FExcelWorkbook.Free; FExcelApplication.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); var iUserLCID: integer; DWResult: DWORD; begin if not FileExists(Testname) then ExcelDatenbank_anlegen; iUserLCID := GetUserDefaultLCID; // Wenn die Datenbank extern über Excel geöffnet ist dann wird sie geschlossen. // wenn diese Datei nicht geschlossen wird, dann kommt es zu einer Exception!!! if FindWindow('XLMain','Microsoft Excel - ' + TestName) <> 0 then SendMessageTimeout(FindWindow('XLMain','Microsoft Excel - ' + TestName), WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG or SMTO_NORMAL, 5000, DWResult); FExcelApplication := TExcelApplication.Create(Nil); FExcelWorkbook := TExcelWorkbook.create(Nil); FExcelWorksheet := TExcelWorksheet.create(Nil); // vorhandener Exceldatei laden !!! wichtig !!! Die Anzahl der emtyParam ist Office-Versions abhängig FExcelApplication.Workbooks.Open(ExtractFilePath(ParamStr(0)) + TestName, emptyParam, emptyParam, emptyParam, emptyParam , emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam , emptyParam, emptyParam, iUserLCID); // Excel soll NICHT angezeigt werden FExcelApplication.visible[iUserLCID] := true; // verbinden des Workbooks und des Worksheets mit der in der exc geladenen Datei FExcelWorkbook.ConnectTo(FExcelApplication.ActiveWorkbook); FExcelWorksheet.ConnectTo(FExcelWorkbook.ActiveSheet as ExcelWorksheet); end; end. |
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Hi,
nur mal so aus der Hüfte geschossen: im FromCreate erzeugst Du Deine FExcel... im FormClose schliesst Du diese soweit OK, aber in ExcelDatenbank_anlegen machst Du das Gleiche noch mal. Das muss in die Hose gehen ! Und im Create der Owner = NIL ist auch nicht so prickelnd. Warum darf das nicht Dein Form1 sein ? |
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Nunja da das Öffnen der Applicationen zeitlichgesehen nach einander erfolgt und das 2. Öffnen erst passiert, wenn alles schon wieder freigegeben ist (es ist also nicht verschachtelt!), rechne ich deswegen eigentlich nicht mit einem Fehler dort. Außerdem wenn die Datei Test.xls exisitert, dann wird das ganze ja auch nur einmal geöffnet.
Gestestet habe ich schonmal: ist Test.xls vorhanden -> 1 Speicherleck, keine Exception ist Test.xls vorhanden und die Speicherstell in FormClose auskommentiert -> alles ok ist Test.xls nicht vorhanden -> 2 Speicherlecks, keine Exception ist Test.xls nicht vorhanden und werden die Speicherstellen auskommentiert geben kommt es zu kein Speicherleck, allerdings wird man gefragt, ob man Speichern möchte (dies will ich ja eigentlich nicht) und ein OleFehler tritt auf nach dem 1. Schließen der Excelapplication. |
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Das Speicherleck, ist die Folge einer - sagen wir mal - ungeschickten Implementation von TOleServer und entzieht sich somit deinem Zugriff. Wenn du allerdings die Events der OleServer gar nicht brauchst, kannst du auch die Interfaces direkt verwenden:
Delphi-Quellcode:
procedure ExcelDatenbank_anlegen;
var sparentroot: string; iUserLCID: integer; FExcelApplication: ExcelApplication; // dies sind Interfaces, keine Klassen! FExcelWorkbook: ExcelWorkbook; FExcelWorksheet: ExcelWorksheet; begin sparentroot := ExtractFilePath(ParamStr(0)); iUserLCID := GetUserDefaultLCID; FExcelApplication := CoExcelApplication.Create; FExcelApplication.Workbooks.Add(emptyparam, iUserLCID); FExcelWorkbook := FExcelApplication.ActiveWorkbook; FExcelWorkbook.Worksheets.Add(emptyParam, emptyParam, emptyParam, emptyParam, iUserLCID); FExcelWorksheet := FExcelWorkbook.ActiveSheet as ExcelWorksheet; FExcelWorksheet.Cells.Item[3,1] := 'Hallo'; FExcelWorksheet.Cells.Item[3,2] := 'dies'; FExcelWorksheet.Cells.Item[3,3] := 'ist'; FExcelWorksheet.Cells.Item[3,4] := 'ein'; FExcelWorksheet.Cells.Item[3,5] := 'Test'; FExcelWorkbook.Close(true, sparentroot + Testname, emptyParam, iUserLCID); // Speichert die Änderungen in Excel } end; |
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Danke dir Uwe, werde es morgen gleich mal probieren. Muss hier zu Hause erstmal alles runterladen.
|
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Hallo und Guten Morgen an alle DP´ler,
Habe alles nochmal ein wenig mit Uwes Hinweisen umgearbeitet und die Routine sieht jetzt wie folgt aus:
Delphi-Quellcode:
Es gibt keine Speicherlecks mehr aber eine Frage, wenn ich mit den Interfaces arbeite (was ich ja auch mit create mache, also sie erstellen) brauche ich dann wirklich kein Free mehr?
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExcelXP; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private-Deklarationen } public { Public-Deklarationen } end; const Testname = 'Test.xls'; var Form1: TForm1; FExcelApplication: ExcelApplication; FExcelWorkbook: ExcelWorkbook; FExcelWorksheet: ExcelWorksheet; sparentroot: string; iUserLCID: integer; implementation {$R *.dfm} procedure ExcelDatenbank_anlegen; begin FExcelApplication := CoExcelApplication.Create; FExcelApplication.Workbooks.Add(emptyparam, iUserLCID); FExcelWorkbook := FExcelApplication.ActiveWorkbook; FExcelWorkbook.Worksheets.Add(emptyParam, emptyParam, emptyParam, emptyParam, iUserLCID); FExcelWorksheet := FExcelWorkbook.ActiveSheet as ExcelWorksheet; FExcelWorksheet.Cells.Item[3,1] := 'Hallo'; FExcelWorksheet.Cells.Item[3,2] := 'dies'; FExcelWorksheet.Cells.Item[3,3] := 'ist'; FExcelWorksheet.Cells.Item[3,4] := 'ein'; FExcelWorksheet.Cells.Item[3,5] := 'Test'; FExcelApplication.visible[iUserLCID] := true; end; procedure ExcelDatenbank_oeffnen; begin FExcelApplication := CoExcelApplication.Create; FExcelApplication.Workbooks.Open(ExtractFilePath(ParamStr(0)) + TestName, emptyParam, emptyParam, emptyParam, emptyParam , emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam , emptyParam, emptyParam, iUserLCID); FExcelApplication.visible[iUserLCID] := true; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin // Speichern und Schließen von Excel FExcelApplication.ActiveWorkbook.Close(true, sparentroot + Testname, emptyParam, iUserLCID); end; procedure TForm1.FormCreate(Sender: TObject); var DWResult: DWORD; begin sparentroot := ExtractFilePath(ParamStr(0)); iUserLCID := GetUserDefaultLCID; if FindWindow('XLMain','Microsoft Excel - ' + TestName) <> 0 then SendMessageTimeout(FindWindow('XLMain','Microsoft Excel - ' + TestName), WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG or SMTO_NORMAL, 5000, DWResult); if not FileExists(Testname) then ExcelDatenbank_anlegen else ExcelDatenbank_oeffnen; end; end. Vielen Dank BAMatze |
Re: Komponente verursacht Fehler beim Beenden von Delphi/Pro
Alle folgenden Variablen gehören unter den Abschnitt private der Klasse TForm1.
Delphi-Quellcode:
Die mit Stern markierten Variablen sind Interface Pointer und unterliegen der Referenzzählung.
FExcelApplication: ExcelApplication; // *
FExcelWorkbook: ExcelWorkbook; // * FExcelWorksheet: ExcelWorksheet; // * sparentroot: string; iUserLCID: integer; Daher ist es sinnvoll, dass diese Variable die gleiche Lebensdauer wie das Formular bekommen. Wenn das Formular stirbt, sorgt unsichtbarer Code vom Delphicompiler dafür, dass auch die Objekte die hinter den Interface Pointern stehen freigegeben werden. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:48 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