Autor |
Beitrag |
CarstenSchmidt
      
Beiträge: 21
Win XP, Win 2000
D6 Pers, D 2005 Prof
|
Verfasst: Fr 29.07.05 10:56
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
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
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: Fr 29.07.05 11: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 
      
Beiträge: 21
Win XP, Win 2000
D6 Pers, D 2005 Prof
|
Verfasst: Fr 29.07.05 11:26
Sehr schön, danke.
Aber was mache ich dagegen? Ich habe mit handles und Device Contexten keine Erfahrung.
Gruß
Carsten
|
|
Stefan.Buchholtz
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: Fr 29.07.05 11: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 ( 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
      
Beiträge: 414
Erhaltene Danke: 23
|
Verfasst: Fr 29.07.05 11: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
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: Fr 29.07.05 12: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 
      
Beiträge: 21
Win XP, Win 2000
D6 Pers, D 2005 Prof
|
Verfasst: Fr 29.07.05 12:39
Danke für die Tipps. Ich werde es heute abend mal ausprobieren.
Carsten
|
|
hallo
      
Beiträge: 450
WIN XP, SuSE 9.3
D3 Prof, D6 Pers, 2005 Pers
|
Verfasst: Fr 29.07.05 12: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!
_________________ Der beste je Programmierte Trojaner: Windows XP
Wäre es nicht adequat, den Usus heterogener Termini zu minimieren?
|
|
CarstenSchmidt 
      
Beiträge: 21
Win XP, Win 2000
D6 Pers, D 2005 Prof
|
Verfasst: Fr 29.07.05 19: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
|
|
|