الحصول على معلومات البرامج العامله داخل الويندوز

الناقل : elmasry | الكاتب الأصلى : tmaaa | المصدر : www.arabteam2000-forum.com

السلام عليكم
* هذا الموضوع للغرض التعليمي لاغير . بالنسبه للمبرمجين المحترفين يفضل تعدي هذا الموضوع :) .
قبل فتره كنت قد بدأت في عمل برنامج يقوم باعطاء معلومات عن الــ Processes الشغاله حاليا في الكمبيوتر . هناك العديد من البرامج التي تقوم بهذا الشئ احدها Task Manager التابع لـ win2k/xp , او برنامج pviewer الذي ياتي مع Support Tools الموجود ضمن win2k/xp CD .
احد البرامج الجيده ايضا والتي افضلها هو PrcView
http://www.prcview.com وغيرها ...
لاحظت ان البرامج الغير تابعه لمايكروسوفت جميعها تستخدم ملف DLL اسمه PSAPI.DLL ياتي مع الـ VC , يمكن تنزيله من صفحه MS ايضا. هذا الملف يقوم باستدعاء عدد من دوال الــ native api التي تساعد في تجميع المعلومات الخاصه بالــ Processes و الــ Threads ...
لاحظت ان TaskManager و Pviewer تستدعي نفس الدوال بصوره مباشره دون اعتماد على الـ DLL المذكور ..
هنا سأضع كود يعطي بعض المعلومات عن الـ Process الحاليه.
بالنسبه للبرنامج الذي اقوم ببرمجته - ان شاء الله - اضع كوده في العطله بعد شهر تقريبا , البرنامج يعتمد تماما على دوال native api ( اي انه لا يعتمد على PSAPI.DLL ) .
Add a button and Memo to a form

 
// Add this after the declaration of form calss  
  TPDword=^DWORD;
  PProcess_Basic_Information =^TProcess_Basic_Information;
  TProcess_Basic_Information = record
        ExitStatus : DWORD;
        PebBaseAddress : DWORD;
        AffinityMask : DWORD;
        BasePriority : DWORD;
        UniqueProcessId : ULONG;
        InheritedFormUniqueProcessId : ULONG;
  end;
  PProcess_Quata_Limits=^TProcess_Quata_Limits;
  TProcess_Quata_Limits=record
        PagedPoolLimit : ULONG;
        NonPagedPoolLimit : ULONG;
        MinimumWorkingSetSize : ULONG;
        MaximumWorkingSetSize : ULONG;
        PagefileLimit : ULONG;
        TimeLimit : LARGE_INTEGER;
  end;
  PProcess_IO_Counters=^TProcess_IO_Counters;
  TProcess_IO_Counters=record
        ReadOperationCount : LARGE_INTEGER;
        WriteOperationCount : LARGE_INTEGER;
        OtherOperatoinCount : LARGE_INTEGER;
        ReadTransferCount : LARGE_INTEGER;
        WriteTransferCount : LARGE_INTEGER;
        OtherTransferCount : LARGE_INTEGER;
  end;
function NtQueryInformationProcess
              (
                ProcessHandle : Thandle;
                PrcInfoClass : DWORD ;
                PrcInfo : Pointer ;
                PrcInfoLength : ULONG;
                returnlength : TPDword
              ):
                DWORD; stdcall ;external 'ntdll.dll' name 'NtQueryInformationProcess';
...
// Button Click event
procedure TForm1.Button1Click(Sender: TObject);
var
status : DWORD;
retlen : DWORD;
Prc_Basic_Info : TProcess_Basic_Information;
Prc_Quta_Limits : TProcess_Quata_Limits;
Prc_IO_Counter : TProcess_IO_Counters ;
hProcess : THandle;
begin
hProcess := GetCurrentProcess();  
status:=NtQueryInformationProcess
        (
          hProcess,
          0,//ProcessBasicInformatio
          @Prc_Basic_Info,
          sizeof(TProcess_Basic_Information),
          @retlen
        );
if(status<>0) then
   exit;
status:=NtQueryInformationProcess
        (
          hProcess,
          1,//ProcessQuataLimits
          @Prc_Quta_Limits,
          sizeof(TProcess_Quata_Limits),
          @retlen
        );
if(status<>0) then
   exit;
status:=NtQueryInformationProcess
        (
          hProcess,
          2,//ProcessIOCounters
          @Prc_IO_Counter,
          sizeof(TProcess_IO_Counters),
          @retlen
        );
if(status<>0) then
   exit;
 
Memo1.Clear;
Memo1.Lines.Add('ExitStatus       : '+IntToStr(Prc_Basic_Info.ExitStatus));
Memo1.Lines.Add('PebBaseAddress   : '+IntToStr(Prc_Basic_Info.PebBaseAddress));
Memo1.Lines.Add('AffinityMask     : '+IntToStr(Prc_Basic_Info.AffinityMask));
Memo1.Lines.Add('BasePriority     : '+IntToStr(Prc_Basic_Info.BasePriority));
Memo1.Lines.Add('UniqueProcessId  : '+IntToStr(Prc_Basic_Info.UniqueProcessId));
Memo1.Lines.Add('Parent ProcessId : '+IntToStr(Prc_Basic_Info.InheritedFormUniqueProcessId));
 
Memo1.Lines.Add('PagedPool        : '+IntToStr(Prc_Quta_Limits.PagedPoolLimit));
Memo1.Lines.Add('NonPagedPool     : '+IntToStr(Prc_Quta_Limits.NonPagedPoolLimit));
Memo1.Lines.Add('MinWorkingSet    : '+IntToStr(Prc_Quta_Limits.MinimumWorkingSetSize));
Memo1.Lines.Add('MaxWorkingSet    : '+IntToStr(Prc_Quta_Limits.MaximumWorkingSetSize));
Memo1.Lines.Add('Pagefile         : '+IntToStr(Prc_Quta_Limits.PagefileLimit));
Memo1.Lines.Add('TimeLimit        : '+IntToStr(Prc_Quta_Limits.TimeLimit.QuadPart));
 
Memo1.Lines.Add('I/O Read         : '+IntToStr(Prc_IO_Counter.ReadOperationCount.QuadPart));
Memo1.Lines.Add('I/O Write        : '+IntToStr(Prc_IO_Counter.WriteOperationCount.QuadPart));
Memo1.Lines.Add('I/O Other        : '+IntToStr(Prc_IO_Counter.OtherOperatoinCount.QuadPart));
Memo1.Lines.Add('I/O Read Byte    : '+IntToStr(Prc_IO_Counter.ReadTransferCount.QuadPart));
Memo1.Lines.Add('I/O Write Byte   : '+IntToStr(Prc_IO_Counter.WriteTransferCount.QuadPart));
Memo1.Lines.Add('I/O Other  Byte  : '+IntToStr(Prc_IO_Counter.OtherTransferCount.QuadPart));
end;

بالنسبه للدوال والانواع المعرفه في الكود يمكن مراجعه كتاب Window NT/2000 Native API , رابط تنزيل الكتاب موجود في موضوع Delphi&Native API و في موضوع لي في قسم الفيجوال سي .
يمكن مقارنه النتائج مع القيم في TaskManager . طبعا هناك العديد من المعلومات التي يمكن الحصول عليها .

----------
By kcahcn , Computer Idiot Organization

(f)