![]() |
Memory-Leak WMI
Moin,
Ich mache grad die ersten Gehversuche mit WMI. WMI scheint recht nützlich zu sein um an verschiedene Informationen zu kommen. In meinem Beispiel geht es um Prozesse. Ich weiss zwar das es andere Möglichkeieten gibt an diese Informationen zu kommen z.B. Toolhlp32, aber mir geht es halt darum WMI zu verstehen. Leider sind meine bisherigen Versuche nicht von erfolg gekrönt, das Ganze funktioniert zwar, aber verursacht Memory-Leaks. Ich habe das ganze soweit verfolgen können das Die Memory-Leaks irgendwie in der WMI entstehen. Denke ich zumindestens. Aber komme irgendwie nicht zu einer Lösung, irgendwer ne Idee ? Hier mal der Code :
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, WbemScripting_TLB, ActiveX, StdCtrls, ExtCtrls; Type TForm1 = class(TForm) Memo1: TMemo; Timer1: TTimer; procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } function getWMIProcess : TStringList; end; var Form1: TForm1; implementation {$R *.dfm} function TForm1.getWMIProcess : TStringList; var l_WMILocator: ISWbemLocator; l_WMIServices: ISWbemServices; l_WMIObjectDefinition: ISWbemObject; l_WMIObjectSet: SWbemObjectSet; l_WMIObjectInstances: IEnumVariant; l_WMIObject: ISWbemObject; l_WMIPropertySet: ISWbemPropertySet; l_WMIProperty: ISWbemProperty; l_TempObj: OleVariant; l_ObjValue: Cardinal; WMI_Name : String; WMI_PID : uint64; WMI_Tick : uint64; WMI_UTime : uint64; WMI_KTime : uint64; WMI_Mem : uint64; begin result := TStringList.Create; l_WMILocator := CoSWbemLocator.Create; l_WMIServices := L_WMILocator.ConnectServer('.', 'root\CIMV2', '', '', '', '', 0, nil); l_WMIObjectDefinition := l_WMIServices.Get('Win32_Process', wbemFlagUseAmendedQualifiers, nil); l_WMIObjectSet := l_WMIObjectDefinition.Instances_(0, nil); l_WMIObjectInstances := (l_WMIObjectSet._NewEnum) as IEnumVariant; while (l_WMIObjectInstances.Next(1, l_TempObj, l_ObjValue) = S_OK) do begin WMI_Tick := GetTickCount; l_WMIObject:= IUnknown(l_TempObj) as SWBemObject; l_WMIPropertySet := l_WMIObject.Properties_; l_WMIProperty := l_WMIPropertySet.Item('Name', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_Name := l_WMIProperty.Get_Value else WMI_Name := 'N/A'; l_WMIProperty := l_WMIPropertySet.Item('ProcessId', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_PID := l_WMIProperty.Get_Value else WMI_PID := 0; l_WMIProperty := l_WMIPropertySet.Item('WorkingSetSize', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_Mem := l_WMIProperty.Get_Value div 1024 else WMI_Mem := 0; l_WMIProperty := l_WMIPropertySet.Item('UserModeTime', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_UTime := l_WMIProperty.Get_Value else WMI_UTime := 0; l_WMIProperty := l_WMIPropertySet.Item('KernelModeTime', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_KTime := l_WMIProperty.Get_Value else WMI_KTime := 0; result.add(IntToStr(WMI_PID) + ' : ' + WMI_Name + ' - ' + IntToStr(WMI_Mem) + ' K ' + InttoStr(WMI_UTime + WMI_KTime)); end; l_WMILocator := nil; l_WMIServices := nil; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Memo1.Lines := getWMIProcess; end; end. |
Re: Memory-Leak WMI
Deine Funktion erzeugt eine TStringList. Aber niemand gibt diese StringList wieder frei => MemoryLeak.
|
Re: Memory-Leak WMI
Tjo, leuchtet ein, aber irgendwie brauch ich ja die TStringList als Ergebnis der Function.
Aber wie krieg ich den Speicher wieder frei ? result.free erzeugt ein Exception, das mag er nicht. Wenn ich mir vorher ein Stringlist erstelle :
Delphi-Quellcode:
Dann gibts auch ne Exception!
function TForm1.WhatEver : TStringList;
var StList : TStringList; Begin StList := TStringList.Create; // Erstellen try blah blah blah StList.add(Result of blah); result := StList; // Zuweisen des Ergebnisses an Result finally StList.Free; // Speicher freigeben end; end; Confused, scheint nicht so einfach zu sein ne TStringlist als Rückgabewert zu haben. |
Re: Memory-Leak WMI
Übergib' einfach einen Parameter vom Typen TStrings.
Dadurch kannst du eine StringList reinwerfen oder die items einer ListBox, etc. Vergesse aber nicht BeGinUpdate am Anfang und EndUpdate am Ende auszuführen. Sonst wird das schnell sehr lahmarschig wenn jemand die items eines Controls übergibt. ;) |
Re: Memory-Leak WMI
Öhhh, Bahnhof :-)
Ich doof (oder unwissend). Haste mal nen Bleistift ? |
Re: Memory-Leak WMI
Er meint das so...
Delphi-Quellcode:
Gruss
procedure TForm1.getWMIProcess(Liste:TStrings);
var l_WMILocator: ISWbemLocator; l_WMIServices: ISWbemServices; l_WMIObjectDefinition: ISWbemObject; l_WMIObjectSet: SWbemObjectSet; l_WMIObjectInstances: IEnumVariant; l_WMIObject: ISWbemObject; l_WMIPropertySet: ISWbemPropertySet; l_WMIProperty: ISWbemProperty; l_TempObj: OleVariant; l_ObjValue: Cardinal; WMI_Name : String; WMI_PID : uint64; WMI_Tick : uint64; WMI_UTime : uint64; WMI_KTime : uint64; WMI_Mem : uint64; begin l_WMILocator := CoSWbemLocator.Create; l_WMIServices := L_WMILocator.ConnectServer('.', 'root\CIMV2', '', '', '', '', 0, nil); l_WMIObjectDefinition := l_WMIServices.Get('Win32_Process', wbemFlagUseAmendedQualifiers, nil); l_WMIObjectSet := l_WMIObjectDefinition.Instances_(0, nil); l_WMIObjectInstances := (l_WMIObjectSet._NewEnum) as IEnumVariant; while (l_WMIObjectInstances.Next(1, l_TempObj, l_ObjValue) = S_OK) do begin WMI_Tick := GetTickCount; l_WMIObject:= IUnknown(l_TempObj) as SWBemObject; l_WMIPropertySet := l_WMIObject.Properties_; l_WMIProperty := l_WMIPropertySet.Item('Name', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_Name := l_WMIProperty.Get_Value else WMI_Name := 'N/A'; l_WMIProperty := l_WMIPropertySet.Item('ProcessId', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_PID := l_WMIProperty.Get_Value else WMI_PID := 0; l_WMIProperty := l_WMIPropertySet.Item('WorkingSetSize', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_Mem := l_WMIProperty.Get_Value div 1024 else WMI_Mem := 0; l_WMIProperty := l_WMIPropertySet.Item('UserModeTime', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_UTime := l_WMIProperty.Get_Value else WMI_UTime := 0; l_WMIProperty := l_WMIPropertySet.Item('KernelModeTime', 0); if not VarIsNull(l_WMIProperty.Get_Value) then WMI_KTime := l_WMIProperty.Get_Value else WMI_KTime := 0; Liste.Append(IntToStr(WMI_PID) + ' : ' + WMI_Name + ' - ' + IntToStr(WMI_Mem) + ' K ' + InttoStr(WMI_UTime + WMI_KTime)); end; l_WMILocator := nil; l_WMIServices := nil; end; procedure TForm1.Timer1Timer(Sender: TObject); begin getWMIProcess(Memo1.Lines); end; Thorsten |
Re: Memory-Leak WMI
Habs mal so gemacht, funktionieren tuts immer noch genauso wie am Anfang!
NUR leider ist das Memoryleak immer noch vorhanden. Kann man ja Wunderbar in der Ausgabe sehen. Der Timer steht auf 250ms. Speicher beim Start: ca 7700K Nach 1 Min : ca. 16000K Nach 2 Min : ca. 30000K So nach einigen Minuten 80000K Das sieht nich gut aus! wtf wenn ich das mal so sagen darf :-) Achja, aus dem Liste.Append hab ich Liste.add gemacht. Der Aufruf erfolgt so :
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin Memo1.Clear; getWMIProcess(Memo1.Lines); end; |
Re: Memory-Leak WMI
Vielleicht hast du ja noch mehr Speicherprobleme, an anderer Stelle.
Schau dir mal ![]() Gruss Thorsten |
Re: Memory-Leak WMI
Hab ich schon, der schmeisst 1000 Sachen raus und will immer die System.pas, hab ich nicht.
Zudem besteht mein Programm nur aus dieser einen Funktion, eigentlich recht übersichtlich. Im Moment komm ich immer mehr zu dem Schluss das der Fehler im WMI liegt und nicht in meiner Source. Den, vielmehr als eben WMI aufrufen macht mein Code ja nicht. Hab das Ganze mal nachvollzogen indem ich die Stringlist rausgeworfen habe und einfach den Speicherbedarf per Label ausgebe : Label1.Caption := IntToStr(WMI_Mem); Memory-Leak immer noch vorhanden. |
Re: Memory-Leak WMI
Ist dann wohl so. Leider kann man deinen Code nicht testen, schade.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:14 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 by Thomas Breitkreuz