cstamas
cstamas

Reputation: 410

collecting wmi performance counters with refresher object

I am a beginner in c# and .net. My intention as a unix guy is to provide a service for the windows team collecting performance data from windows servers and recoding them in graphite (via StatsD).

I found a source code which seems to do exactly that except that it uses a wrong interface (wrong level of abstraction) it seems. e.g. the labels are translated in localized windows versions (which is insane) and that makes the use of this service infeasible.

Using wmi performance counters seems to be the way to go, but I would like to query efficiently and found that using a refresher object for this is the recommended solution however I do not know how to do that.

Somehow related I found an answer for querying the values once which I include here as a reference.

The question is:

Thanks

Upvotes: 3

Views: 1721

Answers (1)

Cameron Tinker
Cameron Tinker

Reputation: 9789

Here is what I use for gathering information about disk usage via WMI in C#:

private List<DiskInfo> GetDiskInfo()
{
    List<DiskInfo> disks = new List<DiskInfo>();
    SelectQuery query = new SelectQuery("SELECT Size, FreeSpace, Name, FileSystem FROM Win32_LogicalDisk WHERE DriveType = 3");

    ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(scope, query);
    ManagementObjectCollection collection = moSearcher.Get();
    foreach (ManagementObject res in collection)
    {
        float size = Convert.ToSingle(res["Size"]) / 1024f;
        float usedSpace = size - (Convert.ToSingle(res["FreeSpace"]) / 1024f);
        DiskInfo di = new DiskInfo();
        di.Name = res["Name"].ToString();
        di.Size = ConvertVal(size);
        di.UsedSpace = ConvertVal(usedSpace);
        if (size > 0)
        {
            di.PercentUsed = ((usedSpace / size) * 100).ToString("N0");
        }
        else
        {
            di.PercentUsed = "0";
        }
        if (res["FileSystem"] != null)
        {
            di.FileSystem = res["FileSystem"].ToString();
            disks.Add(di);
        }                               
    }

    return disks;
}

// handles returning the correct units    
private string ConvertVal(float value)
    {           
        float K = value;
        float M = value / 1024f;
        float G = M / 1024f;
        float T = G / 1024f;
        string unit = "KB";
        float val = K;            

        if (K >= 1024)
        {
            unit = "MB";
            val = M;
        }

        if (M >= 1024)
        {
            unit = "GB";
            val = G;
        }

        if (G >= 1024)
        {
            unit = "TB";
            val = T;
        }

        return val.ToString("N2") + unit;
    }

I primarily use the code above in conjunction with a full ComputerInfo class that I can call from jQuery AJAX every few seconds on an ASP.NET MVC service that returns JSON to the browser and I construct the page on the fly with the data provided.
Here's my DiskInfo class for making data easier to display:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComputerInfo.Models
{
    public class DiskInfo
    {
        public string Name { get; set; }
        public string Size { get; set; }
        public string UsedSpace { get; set; }
        public string PercentUsed { get; set; }
        public string FileSystem { get; set; }
    }
}

I hope this helps. Let me know if you need anything else in the answer.

Upvotes: 2

Related Questions