🗿

[C#/WMI] WMIで、あるプロセスのCPU時間やメモリ使用量をとる

2021/08/25に公開

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

あるプロセスが消費しているCPU時間(カーネル時間/ユーザー時間)を取りたいときにPerformanceConterクラスを使って取ろうとしていたが、PerformanceConterクラスを使うと何か遅い気がする。

他の取り方がないか調べている中で、WMIという方法があることを知った。
WMIでどうやってCPU時間等をとれるのか調べたい。

※この記事を書いてる途中に、以前似たことを書いたのを思い出した。
 そっちの方がまとまってるので、そちらも参照↓
https://zenn.dev/tera1707/articles/87bf99621770e1

WMIについて

WMIとは「Windows Management Instrumentation」の略で、Windows OSを管理することを目的にMicrosoftが開発した技術。WMIを活用することで、Windowsシステムの状態を示す情報を取得できる、とのこと。
https://www.manageengine.jp/products/OpManager/wmi-monitoring.html

またWMIをコマンドラインから使うために、WMIC(Windows Management Instrumentation Command-line)というのがあるらしい。(今回はやらない)

C#からWMIを使う

C#からWMIを使うには、今回調べた限りでは、下記のようにすればよい。

  • System.Management.dllを参照に追加する
  • 下記のようなクラスを使用する
    • ManagementScope
    • ObjectQuery
    • ManagementObjectSearcher

サンプルコード

using System;
using System.Management;//System.Management.dllを参照に追加
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        // Win32_PerfRawData_PerfProc_Process の仕様
        // https://docs.microsoft.com/en-us/previous-versions/aa394323(v=vs.85)

        // エントリーポイント
        static void Main(string[] args)
        {
            ManagementScope scope = new ManagementScope("\\\\.\\ROOT\\cimv2");

            ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_PerfRawData_PerfProc_Process");
            //ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=\"12452\""); // Pidで対象を絞る場合
            //ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_PerfRawData_PerfProc_Process Where Name=\"Idle\"");       // パフォーマンスカウンタのインスタンス名で対象を絞る場合

            ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);

            while (true)
            {
                Console.Clear();

                ManagementObjectCollection queryCollection = searcher.Get();

                foreach (ManagementObject m in queryCollection)
                {
                    // WMIオブジェクトのプロパティを取得して表示
                    Console.WriteLine("{0}, {1}, {2}, {3}, {4}", m["Name"], m["IDProcess"], m["PercentProcessorTime"], m["PrivateBytes"], (uint.Parse(m["IOWriteBytesPerSec"].ToString())));
                }

                Thread.Sleep(1000);
            }
        }
    }
}

難点

CPU使用率はとれないが、CPU時間がとれる。そこからCPU使用率は計算できそう。

参考

Win32_PerfRawData_PerfProc_Processでなんの情報が取れるかは下記を参照。
https://docs.microsoft.com/en-us/previous-versions/aa394323(v=vs.85)

WMIでいろいろできるツール??

https://www.microsoft.com/en-us/download/details.aspx?id=8572

WMI詳しい情報

https://uchukamen.com/Programming/WMI/

cimvってなにか?

https://forest.watch.impress.co.jp/docs/review/702170.html
image.png

トータル(PC全体)のCPU使用率(CPU時間?)をとる

https://docs.microsoft.com/ja-jp/windows/win32/wmisdk/monitoring-performance-data#using-raw-performance-data-classes

取れる情報の参考 ※公式がなぜかみあたらない。。
https://www.activexperts.com/admin/scripts/wmi/perl/0454/

使えるクラスのリスト??
https://docs.microsoft.com/en-us/previous-versions/visualstudio/windows-sdk/cc173990(v=vs.90)

wbemtest(WMIをいろいろ実験できるツール)

https://social.technet.microsoft.com/Forums/windowsserver/ja-JP/8bcc233d-43c2-4c32-8b9a-7b6d39930e6a/windowsserver2008-r2-cpu?forum=windowsserver2008ja

Discussion