2015-11-20 1 views
1

Как я могу прочитать PhysicalDisk\Average Disk sec/Read и другие подобные счетчики производительности, от Delphi?Как я могу прочитать PerfMon PhysicalDisk Average Disk sec/Read counter из Delphi?

Я подозреваю, что я должен использовать генератор классов WMI класса RRUZ, но я не знаю, какой класс мне нужен или как его использовать.

ответ

2

Это поможет вам начать:

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    ActiveX, 
    ComObj, 
    Variants; 

procedure Main; 
var 
    objWMIService: OleVariant; 
    colItems: OleVariant; 
    colItem: OleVariant; 
    oEnum: IEnumvariant; 
    iValue: LongWord; 

    function GetWMIObject(const objectName: String): IDispatch; 
    var 
    chEaten: Integer; 
    BindCtx: IBindCtx; 
    Moniker: IMoniker; 
    begin 
    OleCheck(CreateBindCtx(0, BindCtx)); 
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, 
     Moniker)); 
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result)); 
    end; 

begin 
    objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2'); 
    colItems := objWMIService.ExecQuery 
    ('Select * from Win32_perfformatteddata_perfdisk_LogicalDisk', 'WQL', 0); 
    oEnum := IUnknown(colItems._NewEnum) as IEnumvariant; 
    while oEnum.Next(1, colItem, iValue) = 0 do 
    begin 
    Writeln(colItem.Name + ', ' + IntToStr(colItem.AvgDiskSecPerRead)); 
    end; 
end; 

begin 
    try 
    CoInitialize(nil); 
    try 
     Main; 
     Readln; 
    finally 
     CoUninitialize; 
    end; 
    except 
    on E: Exception do 
    begin 
     Writeln(E.Classname, ': ', E.Message); 
     Readln; 
    end; 
    end; 
end. 

Я предполагаю, что вы знаете достаточно о WMI, чтобы сделать все остальное. Документация для этого класса WMI находится здесь: Win32_PerfFormattedData_PerfDisk_LogicalDisk.

Если вы хотите, чтобы построить это на вершине библиотек Родриго, а затем я отсылаю вас здесь: https://github.com/RRUZ/delphi-wmi-class-generator/blob/master/root_CIMV2/uWin32_PerfFormattedData_PerfDisk_LogicalDisk.pas

+0

Fantastic. Благодаря! –

1

В случае это может быть полезно, вы также можете прочитать данные о производительности непосредственно. Вот простой пример, используя мой PerfUtils и перевод winperf.h из JEDI API Library:

program test; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    System.SysUtils, 
    JwaWinPerf, 
    PerfUtils in 'PerfUtils.pas'; 

const 
    CtrAvgDiskSecPerRead = 208; 

procedure GetCounterAverageTimer(Obj: PPerfObjectType; NameIndex, InstanceIndex: Cardinal; 
    out TimerValue, BaseValue: Cardinal); 
var 
    CounterTimer, CounterBase: PPerfCounterDefinition; 
    Instance: PPerfInstanceDefinition; 
begin 
    TimerValue := 0; 
    BaseValue := 0; 
    // average timer counter 
    CounterTimer := GetCounterByNameIndex(Obj, NameIndex); 
    if not Assigned(CounterTimer) or (CounterTimer^.CounterType <> PERF_AVERAGE_TIMER) then 
    Exit; 
    // average base counter 
    CounterBase := GetNextCounter(CounterTimer); 
    if not Assigned(CounterBase) or (CounterBase^.CounterNameTitleIndex <> NameIndex) or 
    (CounterBase^.CounterType <> PERF_AVERAGE_BASE) then 
    Exit; 
    Instance := GetInstance(Obj, InstanceIndex); 
    if not Assigned(Instance) then 
    Exit; 
    TimerValue := GetCounterValue32(Obj, CounterTimer, Instance); 
    BaseValue := GetCounterValue32(Obj, CounterBase, Instance); 
end; 

function GetPhysicalDiskAvgSecPerRead(DiskInstance: Integer; Data1, Data2: PPerfDataBlock): Double; 
var 
    Obj1, Obj2: PPerfObjectType; 
    TimerValue1, TimerValue2, BaseValue1, BaseValue2: Cardinal; 
begin 
    Result := 0; 
    Obj1 := GetObjectByNameIndex(Data1, ObjPhysicalDisk); 
    Obj2 := GetObjectByNameIndex(Data2, ObjPhysicalDisk); 
    if not Assigned(Obj1) or not Assigned(Obj2) then 
    Exit; 
    GetCounterAverageTimer(Obj1, CtrAvgDiskSecPerRead, DiskInstance, TimerValue1, BaseValue1); 
    GetCounterAverageTimer(Obj2, CtrAvgDiskSecPerRead, DiskInstance, TimerValue2, BaseValue2); 
    if (TimerValue2 = TimerValue1) or (BaseValue2 = BaseValue1) then 
    Exit; 

    Result := (Int64(TimerValue2 - TimerValue1)/Data1^.PerfFreq.QuadPart)/Int64(BaseValue2 - BaseValue1); 
end; 

function GetDiskInstanceName(DiskInstance: Integer; Data: PPerfDataBlock): WideString; 
var 
    Obj: PPerfObjectType; 
    Instance: PPerfInstanceDefinition; 
begin 
    Result := ''; 
    Obj := GetObjectByNameIndex(Data, ObjPhysicalDisk); 
    if not Assigned(Obj) then 
    Exit; 
    Instance := GetInstance(Obj, DiskInstance); 
    if not Assigned(Instance) then 
    Exit; 

    SetString(Result, PWideChar(NativeUInt(Instance) + Instance^.NameOffset), Instance^.NameLength div SizeOf(WideChar)); 
end; 

procedure Main; 
var 
    DiskInstance: Integer; 
    Data1, Data2: PPerfDataBlock; 
begin 
    DiskInstance := 0; // first physical disk by default 
    if ParamCount > 0 then 
    DiskInstance := StrToInt(ParamStr(1)); 
    Data1 := GetPerformanceData(IntToStr(ObjPhysicalDisk)); 
    Writeln(Format('Disk instance %s', [GetDiskInstanceName(DiskInstance, Data1)])); 
    repeat 
    Sleep(1000); 
    Data2 := GetPerformanceData(IntToStr(ObjPhysicalDisk)); 
    Writeln(Format('%.6f', [GetPhysicalDiskAvgSecPerRead(DiskInstance, Data1, Data2)])); 
    Data1 := Data2; 
    until False; 
end; 

begin 
    try 
    Main; 
    except 
    on E: Exception do 
    begin 
     ExitCode := 1; 
     Writeln(Format('[%s] %s', [E.ClassName, E.Message])); 
    end; 
    end; 
end. 
Смежные вопросы