Entwickler-Ecke
Algorithmen, Optimierung und Assembler - "Systemressourcen erschöpft" bei Erstellung von Sc
CarstenSchmidt - Fr 29.07.05 09:56
Titel: "Systemressourcen erschöpft" bei Erstellung von Sc
Moin!
Mein Programm sucht nacheinander zwei Fenster nach Caption, holt das Fenster in den Vordergrund und macht ein Screenshot. Dieser Vorgang wird alle Minute wiederholt. Den Code dazu habe ich aus dem Forum. Obwohl ich mir sicher bin, dass ich alle Handles wieder freigebe, wächst der Speicherbedarf des Programms langsam aber stetig an bis ich nach ein paar Tagen die Meldung bekommen "Systemressourcen erschöpft" und das Programm nicht weitermachen will.
Kann mir jemand sagen, wie ich an den Übeltäter komme oder wo mein Fehler im Code ist?
Danke und Gruß
Carsten
Delphi-Quelltext
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:
| procedure SwitchToThisWindow(h1: hWnd; x: bool); stdcall; external user32 Name 'SwitchToThisWindow';
function FormularSaveScreenShot(FileName: String; h : hWnd): Boolean; var Rec: TRect; iWidth, iHeight: Integer; JpegImg: TJpegImage; bmp : TBitmap; begin JpegImg := TJpegImage.Create; bmp := TBitmap.Create; with bmp do try GetWindowRect(h, Rec); iWidth := Rec.Right - Rec.Left; iHeight := Rec.Bottom - Rec.Top; Width := iWidth; Height := iHeight; BitBlt(Canvas.Handle, 0, 0, iWidth, iHeight, GetWindowDC(h), 0, 0, SRCCOPY); Result := True; JpegImg.assign(bmp); try JpegImg.SaveToFile(Filename) except Result := False end; finally ReleaseDC(h, GetWindowDC(h)); Free; JpegImg.Free; end; end;
procedure TForm1.Button4Click(Sender: TObject); var h1,h2 : hwnd; time :Tdatetime; begin if edit1.Text > '' then begin h1 := findwindow(nil, PCHAR(edit1.text)); if h1 = 0 then exit; SwitchToThisWindow(h1, True); sleep(2000); time := now; FormularSaveScreenShot(edit1.text+'.jpg',h1); label1.Caption := formatdatetime('dd.mmmm. hh:nn:ss', time); label6.Caption := inttostr(strtoint(label6.Caption)+1); end; if edit2.Text > '' then begin h2 := findwindow(nil, PCHAR(edit2.text)); if h2 = 0 then exit; SwitchToThisWindow(h2, True); sleep(2000); time := now; FormularSaveScreenShot(edit2.text+'.jpg',h2); label2.Caption := formatdatetime('dd.mmmm. hh:nn:ss', time); label6.Caption := inttostr(strtoint(label6.Caption)+1); end; releasedc(h1,findwindow(nil, PCHAR(edit1.text))); releasedc(h2,findwindow(nil, PCHAR(edit2.text))); end; |
Ich benutze Win XP/2k mit Dephi 2005 Prof.
Stefan.Buchholtz - Fr 29.07.05 10:12
Titel: Re: "Systemressourcen erschöpft" bei Erstellung vo
CarstenSchmidt hat folgendes geschrieben: |
Moin!
Mein Programm sucht nacheinander zwei Fenster nach Caption, holt das Fenster in den Vordergrund und macht ein Screenshot. Dieser Vorgang wird alle Minute wiederholt. Den Code dazu habe ich aus dem Forum. Obwohl ich mir sicher bin, dass ich alle Handles wieder freigebe, wächst der Speicherbedarf des Programms langsam aber stetig an bis ich nach ein paar Tagen die Meldung bekommen "Systemressourcen erschöpft" und das Programm nicht weitermachen will.
Kann mir jemand sagen, wie ich an den Übeltäter komme oder wo mein Fehler im Code ist?
Danke und Gruß
Carsten
Ich benutze Win XP/2k mit Dephi 2005 Prof. |
Ich denke, der Device Context ist das Problem:
Delphi-Quelltext
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:
| function FormularSaveScreenShot(FileName: String; h : hWnd): Boolean; var Rec: TRect; iWidth, iHeight: Integer; JpegImg: TJpegImage; bmp : TBitmap; dc: HDC; begin JpegImg := TJpegImage.Create; bmp := TBitmap.Create; with bmp do try GetWindowRect(h, Rec); iWidth := Rec.Right - Rec.Left; iHeight := Rec.Bottom - Rec.Top; Width := iWidth; Height := iHeight; dc := GetWindowDC(h); BitBlt(Canvas.Handle, 0, 0, iWidth, iHeight, dc, 0, 0, SRCCOPY); Result := True; JpegImg.assign(bmp); try JpegImg.SaveToFile(Filename) except Result := False end; finally ReleaseDC(h, dc); Free; JpegImg.Free; end; end; |
Stefan
CarstenSchmidt - Fr 29.07.05 10:26
Sehr schön, danke.
Aber was mache ich dagegen? Ich habe mit handles und Device Contexten keine Erfahrung.
Gruß
Carsten
Stefan.Buchholtz - Fr 29.07.05 10:35
CarstenSchmidt hat folgendes geschrieben: |
Sehr schön, danke.
Aber was mache ich dagegen? Ich habe mit handles und Device Contexten keine Erfahrung.
Gruß
Carsten |
Probier es mal mit den Änderungen, die ich gemacht habe, aus - so firm bin ich in dem Thema auch nicht, deswegen bin ich mir nicht sicher, ob es das war. Meiner Meinung nach musst du genau den Device Context, den du mit GetWindowDC geholt hast, auch mit ReleaseDC wieder freigeben. Nochmal GetWindowDC auf das gleiche Fentser aufrufen und den dann releasen tut es denke ich nicht.
Wenn es das nicht war, versuch mal mit MemProof (
http://www.automatedqa.com/downloads/memproof/) herauszufinden, was für ein Objekt nicht wieder freigegeben wird. Das könnte dir einen Hinweis geben, wo der Fehler liegt.
Stefan
Tastaro - Fr 29.07.05 10:43
Das Bitmap ist das Problem.
Zu nem Bmp := tbitmap.create; gehört dann auch irgendwann ein Bmp.free, das in dem Code fehlt.
Beste Grüße
Tastaro
Stefan.Buchholtz - Fr 29.07.05 11:10
Tastaro hat folgendes geschrieben: |
Das Bitmap ist das Problem.
Zu nem Bmp := tbitmap.create; gehört dann auch irgendwann ein Bmp.free, das in dem Code fehlt.
Beste Grüße
Tastaro |
Nein, das Free steht ja im finally-Abschnitt - wegen dem
with bmp do try bezieht sich dieses Free auf das bmp. Sowas ist nicht offensichtlich, weswegen in in den Programmierrichtlinien der Firma, in der ich arbeite, die with-Anweisung schlicht verboten wurde - die steht bei uns auf etwa gleicher Stufe wie goto.
Stefan
CarstenSchmidt - Fr 29.07.05 11:39
Danke für die Tipps. Ich werde es heute abend mal ausprobieren.
Carsten
hallo - Fr 29.07.05 11:43
Also Delphi hat mit dem Speicher teilweiße Probleme!
Deswegen würde ich das Programm welches den Screenshot macht, per Timer und Shellexecute aufrufen, und gleich danach wieder beenden!
CarstenSchmidt - Fr 29.07.05 18:11
Danke, das war wahrscheinlich die Lösung. Im Nachhinein ist es eigentlich logisch. Wenn ich das Handle release (tschuldigung, ich meine, wenn ich den Griff freigebe oder loslasse), indem ich einen neuen Griff anfasse:
Delphi-Quelltext
1:
| ReleaseDC(h, GetWindowDC(h)); |
muss natürlich ein Griff immer festgehalten werden. Mit der vorherigen Definition des Griffes und der folgenden Freigabe eben desselben
Delphi-Quelltext
1: 2:
| dc := GetWindowDC(h); ReleaseDC(h, dc); |
passiert das nicht. Bei 2000 Aufrufen der Screenshot Prozedur hatte ich so nur einen Speicherzuwachs von 4 Byte.
Danke für die Hilfe
Carsten
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!