こんにちはみんな!
Firemonkey
私は現在、 ( )のWindows8タスクマネージャーに非常によく似たスタイルの小さなシステム管理ツールを開発していますDelphi XE2
。現時点では、を使用してCPUコア使用量タイルを作成しようとしていTPanels
ます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;
CoreUsage
およびは両方とも、関連するタイプCoreName
の長さのグローバル変数配列です(CoreNameは、、CoreUsageは)。これに伴う問題は、コアごとの基準(これが私の意図です)とは対照的に、すべてのパネルで同じ値を示すことです。これは、0..63を通過せず、代わりに最初の値のみを取得するようなものです。[0..63]
String
Uint64
私は基本的に、それぞれを配列内の値に割り当てたいと思っています。これにより、ハードコーディングしなくてもコア固有の詳細を簡単に読み取ることができるようになります。開発マシンで完全に作業していたコードでは、手動でこのようなものを使用する必要がありました。
if AnsiContainsText(FWbemObject.Name,'3') then
begin
CoreName[3] := FWbemObject.Name;
CoreUsage[3] := FWbemObject.PercentProcessorTime;
end
ご覧のとおり、何かを期待することはハードコーディングされていますが、3つのCPUを搭載したシステム(上記の例)では不安定になります。明らかに、「3」は0から63までの適切な配列IDに置き換えられました(ただし、0は0,0
具体的に探していました)。これに伴う問題は、CPUフォーマットが実際にはx,y
(x
CPUとy
コアはどこにあるか)であるということです。また、信頼性が低いという単純な理由で使用できることを誇りに思うコードでもありません。たとえば、コア名は、2つの8コアCPU(16の論理コア)を備えたシステムの場合も0,0 .. 0,7
あります。1,0 .. 1,7
同様に重要なのは、コード自体を維持するのは悪夢だったでしょうが、単一の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
しかし、残念ながら、そのような運はありません。何か案は?