| Autor |
Beitrag |
Asmodeus
Hält's aus hier
Beiträge: 8
|
Verfasst: Mi 22.09.10 23:46
Hallo liebe Community,
ich muss sagen, dass ich Dank der Hilfe dieses Forums schon sehr weit mit meinem Programm gekommen bin. Zu fast jedem Problem oder Frage die ich hatte war bereits eine Antwort hier im Forum verfügbar. Jetzt hänge ich aber leider schon seit einiger Zeit fest und komme nicht weiter.
Ich habe eine Vertragsdatenbank programmiert. Die Datenbank selber wurde erstellt mit Access 2003 und beinhaltet nur die Daten. Abfragen werden via SQL aus dem Programm heraus gesteuert. Nun habe ich eine Möglichkeit implementiert Dateianhänge als Link in der Datenbank zu speichern und über Shellapi wieder auszuführen. Bei Dateien, die auf dem lokalen PC abgespeichert sind klappt das wunderbar, bei Dateien auf dem Netzwerk klappt es nicht. Dort stürzt er ab in Bereich Zeile 628 in der Unit kundendatenverwalten. Den Bugreport füge ich separat noch hinzu. Er gibt dabei eine Eaccessviolation aus und einen Fehler beim ERstellen einer neuen SQL Query. Ich verstehe absolut nicht, warum das Problem nur bei Dateianhängen auftritt die sich auf dem Server befinden. Danach ist das Programm auch in einer Fehler-Endlosschleife und muss über den Task Manager beendet werden.
Zu dem Hintergrundsystem kann ich sagen, dass lokal Windows XP SP3 genutzt wird. Das Programm ist als Client lokal bei jedem Nutzer gespeichert. Die Datenbank sowie auch die Dateianhänge sind auf einem Server gespeichert. Entwickelt wird das System auf einem Windows 7 Rechner.
Ich hatte schon versucht mit einer Abfangroutine dieses Fehler zu elminieren und habe die unit sharemem eingebunden, aber nichts hilft davon.
Es wäre echt super nett, wenn jemand einen Anhaltspunkt hätte wo das Problem liegen könnte...
Vielen Dank!
Grüße
Jens
-------------------------------
04.10.2010 UPDATE
Soooo ich habe herausgefunden, dass meine Probleme immer dann stattfinden, wenn ich eine zu große Datei mit Shellexecute aufgerufen habe. Kleinere Dateien funktionen problemlos, aber wenn diese eine bestimmte Anzahl MB überschritten haben, werde Fehler verursacht. Dies geschieht nicht nur im Netzwerk sondern auch lokal, womit ich nun sicher bin, dass der Fehler dort zu suchen ist.
Das Projekt habe ich komplett angehangen und hier ist die entsprechende Prozedur:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115:
| procedure TKundendaten_verwalten_form.GridattachKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); Var Antwort,i : Integer; Pfad :String; Name: String; PfadChar, Pfadchar2 : PWidechar; searchResult : TSearchRec; weiter : Boolean; ReturnValue : THandle; begin If (Key = VK_RETURN) Then begin
if DataModule2.QueryAttach.Eof = TRUE then begin exit; end else begin
Antwort := Application.MessageBox ('Do you really want to open attached file?', 'Question', MB_YesNo+MB_IconQuestion+MB_DefButton2);
if antwort = IDYes then begin TRY Pfad:= ''; Name:= ''; if datamodule2.QueryAttach.Active = TRUE then begin Name:= datamodule2.QueryAttach.FieldByName('Filename').AsString; datamodule2.QueryAttach.Active:= FALSE; datamodule2.QueryAttach.Close; end; datamodule2.QueryAttach.SQL.Clear; datamodule2.QueryAttach.SQL.Text:= 'SELECT * FROM Attachments WHERE VertragID = '+inttostr(VertragID)+' AND Dateiname = '+quotedstr(Name); datamodule2.QueryAttach.Open; datamodule2.QueryAttach.Active:= TRUE; gridattach.DataSource.DataSet:= datamodule2.QueryAttach;
pfad:= Pfad + datamodule2.QueryAttach.FieldByName('Dateipfad').AsString; pfad:= Pfad + datamodule2.QueryAttach.FieldByName('Dateiname').AsString; name:= datamodule2.QueryAttach.FieldByName('Dateiname').AsString; FINALLY if datamodule2.QueryAttach.Active = TRUE then begin datamodule2.QueryAttach.Active:= FALSE; datamodule2.QueryAttach.Close; end; datamodule2.QueryAttach.SQL.Clear; datamodule2.QueryAttach.SQL.Text:= 'SELECT Dateiname as Filename, VertragID as ID FROM Attachments WHERE VertragID = '+inttostr(VertragID); datamodule2.QueryAttach.Open; datamodule2.QueryAttach.Active:= TRUE; gridattach.DataSource.DataSet:= datamodule2.QueryAttach; gridattach.DataSource.DataSet.Filtered:= TRUE;
try <span style="color: red"> getmem(Pfadchar, 256); StringToWideChar(pfad, pfadchar, 256); if fileexists(pfad) then begin
ReturnValue := 0; ReturnValue := ShellExecute(Application.Handle, 'open', Pfadchar, nil, nil, SW_SHOW);
if ReturnValue <= 32 then showmessage(SysErrorMessage(ReturnValue)+ ' '+ IntToStr(ReturnValue)); </span> end else BEGIN Antwort := Application.MessageBox ('Cannot load assigned program or Path is invalid! Do you want to use the Quickfind-Function?', 'Question', MB_YesNo+MB_IconQuestion+MB_DefButton2); if antwort = IDYes then begin pfad:= ''; GetFilesInDirectory(datamodule2.DBPfad,name , Boxresult.Items, TRUE, True);
if boxresult.Count = 0 then begin Showmessage('Couldn''t find your requested file with Quickfind!'); end else begin pfad:= boxresult.Items.Strings[0]; freemem(pfadchar); getmem(Pfadchar, 256); StringToWideChar(pfad, pfadchar, 256); boxresult.Items.Clear; try ShellExecute(Application.Handle, 'open', Pfadchar, nil, nil, SW_SHOW); except Showmessage('Cannot load assigned program!'); end;
end; end; END;
finally freemem(pfadchar); end; END; end; end; end; end; |
Einloggen, um Attachments anzusehen!
Zuletzt bearbeitet von Asmodeus am Mo 04.10.10 20:34, insgesamt 2-mal bearbeitet
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Mi 22.09.10 23:49
Part 2
Einloggen, um Attachments anzusehen!
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Mi 22.09.10 23:50
Part 3
Einloggen, um Attachments anzusehen!
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Mi 22.09.10 23:51
Bug Report (madexcept V 3)
Einloggen, um Attachments anzusehen!
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Mo 04.10.10 19:28
schade, scheint keiner eine LÖsung zu haben 
|
|
Muck
      
Beiträge: 98
Erhaltene Danke: 8
Win 8, Win 7, Vista, Win XP
Delphi XE3, Delphi 2009, Delphi 2007, Delphi 5
|
Verfasst: Mo 04.10.10 20:19
Hallo,
in Deinem "COM PRGL" Abschnitt greifst Du auf query zu, jedoch hast Du vorher "datamodule2.DelQuery" aufgerufen.
In Deiner Procedure DelQuery machst Du ein Free auf das TAdoQuery Object.
Daher Access Violation.
Davon abgesehen: TAdoQuery.Free ruft automatisch ein Close auf. Also kein Grund vorher auf Active=TRUE zu pruefen,
dann Active=false zu setzen und dann noch ein Close. Das ist dreimal das Gleiche.
Ausserdem, suche mal im Forum weshalb man nicht "If Query.Active=TRUE" bunutzen sollte, gleiches fuer
"while query.eof = false"! Besser nutze "while not query.eof"
Statt innerhalb Deiner Procedure die TAdoQuery staendig zu erzeugen und wieder freizugeben, besser nur einmal erzeugen am Anfang,
dann einen Schutzblock und einmal freigeben am Ende.
Innerhalb der Procedure dann die Query schliessen und dann einfach SQL.Text ein neues Kommando zuweisen und die Query wieder oeffnen.
Markus
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
| procedure TKundendaten_verwalten_form.comboboxaktualisieren; Var i, index : Integer; query : TAdoquery; begin for i := 0 to comland.Items.Count do begin comland.Items.Delete(0); end; query:= datamodule2.CreateQuery('SELECT * FROM Länder',0); query.First; while query.Eof = FALSE do begin comland.Items.Add(query.FieldByName('Kennzeichen').AsString); query.Next; end; datamodule2.Delquery(query); index:= comland.Items.IndexOf(datamodule2.QueryKunden.FieldByName('Land').AsString); comland.ItemIndex:= index; for i := 0 to comPRGL.items.Count do begin comPRGL.Items.Delete(0); end; if query.Active = TRUE then begin query.Active:= FALSE; query.Close; end;
query:= datamodule2.CreateQuery('SELECT * FROM Preisgleitklauseln',0); while query.Eof = FALSE do begin comprgl.Items.Add(query.FieldByName('PRC').AsString); query.Next; end; datamodule2.Delquery(query);
query:= datamodule2.CreateQuery('SELECT * FROM KD_PRGL_List WHERE ContractID = '+inttostr(VertragID),0); index:= comprgl.Items.IndexOf('Dummy'); comprgl.Items.Delete(index); while query.Eof = FALSE do begin index:= comprgl.Items.IndexOf(query.FieldByName('PRGL').AsString); comprgl.Items.Delete(index); query.Next; end; datamodule2.Delquery(query); for i := 0 to comPRC.items.Count do begin comPRC.Items.Delete(0); end; comprc.Items.Add('Dummy'); query:= datamodule2.CreateQuery('SELECT * FROM KD_PRGL_List WHERE ContractID = '+inttostr(vertragid),0); query.First; while query.Eof = FALSE do begin comPRC.Items.Add(query.FieldByName('PRGL').AsString); query.Next; end; datamodule2.Delquery(query);
end; |
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Mo 04.10.10 20:39
Hallo Markus,
danke, dass du dir meinen Code angetan hast. Soweit ich erkennen kann, erzeugt dies nicht das Problem, trotzdem vielen Dank für deine Tipps. Ich hatte wirklich versucht alles ziemlich ordentlich zu coden und dachte es wäre ganz gute die Query immer wieder neu zu machen und dann wirder zu löschen, aber war dann scheinbar doch nicht die beste Idee. Werde auf jeden Fall deine Hinweise versuchen umzusetzen, vielen Dank!
Mittlerweile bin ich aber fest davon überzeugt, dass das Problem an der Dateigröße liegt. Kannst du dir vorstellen ob Shellexecute so ein Problem verursachen kann?
Danke!
Grüße
Jens
|
|
Muck
      
Beiträge: 98
Erhaltene Danke: 8
Win 8, Win 7, Vista, Win XP
Delphi XE3, Delphi 2009, Delphi 2007, Delphi 5
|
Verfasst: Mo 04.10.10 20:59
Jens,
man kann natuerlich auch immer ein Create und Free aus ein TAdoObject machen. Nach einem Free (oder bei Dir DelQuery) kannst Du jedoch das TAdoObject nicht mehr benutzen und das ist was Du tust, ungefaehr in Zeilte 628.
Ausserdem noch ein Tip:
Delphi-Quelltext 1: 2: 3: 4:
| for i := 0 to comPRGL.items.Count do begin comPRGL.Items.Delete(0); end; |
Fuer eine Liste mit 10 items rufst Du Delete(0) 11 mal auf.
Besser:
Delphi-Quelltext
loescht alles in einem Rutsch.
Und:
Waehrend du Items einer ComboBox mit dem Inhalt einer Tabelle fuellst solltest du BeginUpdate und Endupdate aufrufen, besonders beim Fuellen groesserer Tablellen oder das ganze wird ewig dauern, da die ComboBox immer wieder neu gezeichnet wird.
Zu der Frage, groesse der Datei:
Ich glaube nicht, dass ShellExecute ein Problem mit Dateien hat, die ein paar MB groesser sind. Wenn das der Fall waere, koennest Du die Dateien ja auch nicht mehr mit Doppelklick direkt vom Explorer oeffnen. Ich glaube viel mehr, dass Du vorher bereits Speicherbreiche ueberschrieben hast und das fuehrt dann spaeter zu diesen Fehlern.
Pruefe Dein Programm mal komplette auf Schutzbloecke und ob Du irgendwo anders noch auf Objecte zugreifst, die breits freigegeben sind. Schalte auch mal die Bereichspruefung in den Compiler optionen an.
Markus
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Do 07.10.10 06:14
Hallo Markus,
vielen Dank für deine Hilfe. Ich arbeite gerade daran den Code zu verbessern gemäß deinen Ausführungen. Kannst du mir bitte nur sagen wie ich am besten die Objekte oder Speicherbereiche überprüfen kann? Das übersteigt irgendwie komplett meinen Kenntnisstand...arbeite sonst immer nur mit dem Fehlern, die der Compiler immer direkt anzeigt.
Danke!
Grüße
Jens
|
|
jaenicke
      
Beiträge: 19339
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 07.10.10 06:16
In den Projektoptionen unter Compiler gibt es die Bereichsüberprüfung.
Im Projektquelltext kannst du ReportMemoryLeaksOnShutdown als erstes auf True setzen, dann werden dir die beim Programmende angezeigt.
|
|
Asmodeus 
Hält's aus hier
Beiträge: 8
|
Verfasst: Di 19.10.10 14:25
Hi Sebastian,
vielen Dank!
MIr ist aufgefallen, dass ich bei Getmem auch zu wenig Speicher zuweise. Dazu habe ich noch einige weitere Schutzblöcke eingebaut. Mittlerweile läuft das Programm schon ganz stabil, werde aber weiter testen um zu sehen, ob es doch noch Probleme gibt.
Schon mal vielen Dank bis jetzt!
Grüße
Jens
|
|
|