Autor Beitrag
CarstenSchmidt
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21

Win XP, Win 2000
D6 Pers, D 2005 Prof
BeitragVerfasst: 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


ausblenden volle Höhe 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';
         {x = false: Size unchanged, x = true: normal size}

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, 00, iWidth, iHeight, GetWindowDC(h), 00, SRCCOPY);
    Result := True;
//    try SaveToFile(Filename) except Result := False end;
    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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Fr 29.07.05 11:12 
Titel: Re: "Systemressourcen erschöpft" bei Erstellung vo
user profile iconCarstenSchmidt 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:

ausblenden 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, 00, iWidth, iHeight, dc00, 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21

Win XP, Win 2000
D6 Pers, D 2005 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Fr 29.07.05 11:35 
user profile iconCarstenSchmidt 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Fr 29.07.05 12:10 
user profile iconTastaro 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21

Win XP, Win 2000
D6 Pers, D 2005 Prof
BeitragVerfasst: Fr 29.07.05 12:39 
Danke für die Tipps. Ich werde es heute abend mal ausprobieren.

Carsten
hallo
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 450

WIN XP, SuSE 9.3
D3 Prof, D6 Pers, 2005 Pers
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21

Win XP, Win 2000
D6 Pers, D 2005 Prof
BeitragVerfasst: 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:

ausblenden 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

ausblenden 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