Linuxだと/proc/stat
を見ればわかるのですが、
Windowsだとなんか色々面倒みたいなので、ウッキウキで作りました。
作ったのですが、構造体とか変数の型とかをWin32APIに合わせるの面倒だったので、
雑に作ってみたところ見事に動いて、半笑いになりました。
結論
コードはGitHubにあげてます。
精度は知らん。
https://github.com/nnahito/nim_windows_total_cpu
コード解説
必要な構造体
とりあえず全部パブリクアクセスで。
LONGとかDWORDはimport winim/lean
をすれば使えるようになります。
type PDH_COUNTER_INFO* = object
dwLength*: DWord
dwType*: DWord
CVersion*: DWord
CStatus*: DWord
lScale*: LONG
lDefaultScale*: LONG
dwUserData*: DWORD_PTR
dwQueryUserData*: DWORD_PTR
szFullPath*: LPSTR
# CPU使用情報が入る構造体
type PPDH_FMT_COUNTERVALUE* = object
CStatus*: DWORD
longValue*: LONG
doubleValue*: DOUBLE
largeValue*: LONGLONG
AnsiStringValue*: LPCSTR
WideStringValue*: LPCWSTR
Win32APIをDLLからロードする
# dllから必要関数のロード
proc PdhOpenQuery*(szDataSource: LPVOID, dwUserData: PDH_COUNTER_INFO, phQuery: ptr int): WINBOOL {.stdcall, dynlib: "Pdh", importc: "PdhOpenQueryA".}
proc PdhAddCounter*(hQuery: int, szFullCounterPath: LPCSTR, dwUserData: DWORD_PTR, phCounter: ptr int): WINBOOL {.stdcall, dynlib: "Pdh", importc: "PdhAddCounterA".}
proc PdhCollectQueryData*(hQuery: int): LONG {.stdcall, dynlib: "Pdh", importc: "PdhCollectQueryData".}
proc PdhGetFormattedCounterValue*(hCounter: int, dwFormat: DWORD, lpdwType: LPDWORD, pValue: ptr PPDH_FMT_COUNTERVALUE) {.stdcall, dynlib: "Pdh", importc: "PdhGetFormattedCounterValue".}
https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhopenquerya
https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhaddcountera
https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhcollectquerydata
https://docs.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhgetformattedcountervalue
あたりを参考に。
CPU使用率の取得
まずはプロセス取得のためにハンドルを取得
discard PdhOpenQuery(nil, dwUserData, &hQuery)
取得したいプロセスのCPU使用率を指定。
今回は全体のCPU使用率なので、_Total
を指定。
var lpcstrStr: LPCSTR
lpcstrStr = "\\Processor(_Total)\\% Processor Time"
discard PdhAddCounter(hQuery, lpcstrStr, 0, &hCounter)
CPU使用率の取得。
PdhCollectQueryDataを2回以上叩く。
前回のPdhCollectQueryData実行時からのCPU使用率が取得されるっぽい。
discard PdhCollectQueryData(hQuery)
取得したCPU使用率を人間様がわかるようにフォーマット
var fmtValue: PPDH_FMT_COUNTERVALUE
PdhGetFormattedCounterValue(hCounter, 512, nil, &fmtValue)
echo fmtValue.doubleValue
なんかこんな感じで取得できる。
宣伝
個人ブログやってます。
https://nnahito.com/