Sco*_*ard 1 delphi wmi delphi-xe2 firemonkey
大家下午好!
我目前正在开发一个小型系统管理工具,其风格类似于Firemonkey(Delphi XE2)中的Windows 8任务管理器.目前,我正在尝试使用TPanels内部创建CPU核心使用率磁贴TGridLayout.我在设计时添加了所有面板,直到我将实际功能排序.
我的问题在于将数据从WMI输出到数组中.我已经有一个不涉及数组的工作版本,但是我在创建更动态的东西时遇到了麻烦,并且不太可能在不同的配置中出现问题.这是目前完全不起作用的代码;
Procedure CoreUsage;
const
WbemUser ='';
WbemPassword ='';
WbemComputer ='localhost';
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
i : Integer;
begin
try
CoInitialize(nil);
try
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation WHERE NOT Name="_Total" AND NOT Name="0,_Total"',
'WQL',
wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
begin
if oEnum.Next(1, FWbemObject, iValue) = 0 then
begin
for i := 0 to 63 do
begin
CoreName[i] := FWbemObject.Name;
CoreUsage[i] := FWbemObject.PercentProcessorTime;
end;
end;
FWbemObject:=Unassigned;
end;
finally
CoUninitialize;
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
CoreUsage并且CoreName都是[0..63]相关类型长度的全局变量数组(CoreName是String,CoreUsage是Uint64).这个问题是它在所有面板中显示相同的值而不是每个核心(这是我的意图).它几乎就像它没有通过0..63,而只是检索第一个值.
我基本上想要将每个值分配给数组中的值,这样我就可以轻松读取特定于核心的详细信息而无需硬编码.在我完全在我的开发机器上工作的代码中,我不得不手动完成并使用这样的东西;
if AnsiContainsText(FWbemObject.Name,'3') then
begin
CoreName[3] := FWbemObject.Name;
CoreUsage[3] := FWbemObject.PercentProcessorTime;
end
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它是硬编码的,可以期待某些东西,但在具有3个CPU的系统中会很脆弱(在上面的例子中).很明显,'3'被替换为相应的数组id,从0到63(尽管0是0,0专门寻找).这个问题是CPU格式实际上是x,y(xCPU 在哪里,y是核心).它也不是代码,我会自豪地使用它的简单基础,它是不可靠的.例如,核心名称可能是0,0 .. 0,7,然后1,0 .. 1,7是具有2个八核CPU(16个逻辑核心)的系统.
同样重要的是,代码本身可能是维护的噩梦,但可能已经缩短为单个for i :=子句并使用IntToStr.但确保其有效的问题仍将存在.
我确信有一种完美的方法可以做到这一点,但我无法弄明白.我确实试过用;
for VarArrayLowBound(FWbemObject.Name, 1) to VarArrayHighBound(FWbemObject.Name, 1) do
和
for VarArrayLowBound(FWbemObject.PercentProcessorTime, 1) to VarArrayHighBound(FWbemObject.PercentProcessorTime, 1) do
但是,唉,没有这样的运气.有任何想法吗?
问题在于你的循环:
if oEnum.Next(1, FWbemObject, iValue) = 0 then
begin
for i := 0 to 63 do
begin
CoreName[i] := FWbemObject.Name;
CoreUsage[i] := FWbemObject.PercentProcessorTime;
end;
end;
Run Code Online (Sandbox Code Playgroud)
你只是FwbemObject一遍又一遍地重复使用64次.
尝试更像的东西:
var
iCurrObj: Integer;
...
iCurrObj := 0;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
CoreName[iCurrObj] := FWbemObject.Name;
CoreUsage[iCurrObj] := FWbemObject.PercentProcessorTime;
Inc(iCurrObj);
// Sanity check for future protection.
if i > High(CoreName) then
Break;
end;
Run Code Online (Sandbox Code Playgroud)
更好的是,让它成为一个实际上让你知道它填充的数组中有多少项的函数.这是一个工作(测试)的例子.(注意:尽管声明了两个数组,但您的问题中的示例甚至都不会编译,因为您的过程名称CoreUsage与数组的名称相同CoreUsage.)
var
CoreName: array[0..63] of string;
CoreUsage: array[0..63] of Extended;
function CoreUse: Integer;
const
WbemUser ='';
WbemPassword ='';
WbemComputer ='localhost';
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
i : Integer;
begin
i := 0;
CoInitialize(nil);
try
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation WHERE NOT Name="_Total" AND NOT Name="0,_Total"', 'WQL', wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
CoreName[i] := FWbemObject.Name;
CoreUsage[i] := FWbemObject.PercentProcessorTime;
Inc(i);
FWbemObject:=Unassigned;
end;
Result := i;
finally
CoUninitialize;
end;
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
951 次 |
| 最近记录: |