3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NimでWindowsのCPU使用率を求める

Posted at

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/

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?