読者です 読者をやめる 読者になる 読者になる

Physics-Station 2

旧 http://physics-station.blogspot.jp/ から当はてなブログに移行しました。間違ってるところがあればコメントください。記述の正確性は保証しません。

C# でWindows 上のプログラムのリソースを監視する

C#で以下のリソースの監視をしたいという需要があったのでサンプルコードを公開する。

  • 使用メモリ量
  • ハンドル数
  • GDI オブジェクト数
  • User オブジェクト数
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport("user32.dll")]
        private static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags);
        const uint GR_GDIOBJECTS = 0;
        const uint GR_USEROBJECTS = 1;
        /// <summary>
        /// GDI オブジェクトの数を返す
        /// </summary>
        /// <returns></returns>
        public static uint GetGDIObjects()
        {
            return GetGuiResources(Process.GetCurrentProcess().Handle, GR_GDIOBJECTS);
        }
        /// <summary>
        /// User オブジェクトの数を返す
        /// </summary>
        /// <returns></returns>
        public static uint GetUserObjects()
        {
            return GetGuiResources(Process.GetCurrentProcess().Handle, GR_USEROBJECTS);
        }
        static void DisplayMemory()
        {
            Console.WriteLine("Total memory  : {0:###,###,###,##0} bytes", GC.GetTotalMemory(false));
            Console.WriteLine("Private bytes   {0:###,###,###,##0} bytes", Process.GetCurrentProcess().PrivateMemorySize64); //プライベート メモリの量
            Console.WriteLine("Handle   count: {0}", Process.GetCurrentProcess().HandleCount); // ハンドル数
            Console.WriteLine("GDI  obj count: {0}", GetGDIObjects());
            Console.WriteLine("User obj count: {0}", GetUserObjects());
            Console.WriteLine();
        }
        static void Main(string[] args)
        {
            for (int i = 0; i < 100; i++)
            {
                using (var p = new Process())
                {
                    p.StartInfo.FileName = "ipconfig";
                    p.Start();
                    p.WaitForExit();
                }
            }
            DisplayMemory();
            GC.Collect(); //ガーベッジ コレクションを行う
            GC.WaitForPendingFinalizers(); //ガーベッジ コレクションが終わるまで待つ
            DisplayMemory();
        }
    }
}

標準出力とタスクマネージャーはこんな感じ

f:id:onsanai:20161004160344p:plain:w600

参照

.net - Finding Memory leaks in C# - Stack Overflow

GDI object count - C# / C Sharp