All posts tagged wmi

This is a bit dated, but the question is about how you get (near) accurate processor information in Windows 2003 with WMI and no external executables.

I wrote this a long time ago for VBS and translated it into C# for my upcoming application: Astronomy. I added some snazzy XAML in there to pimp it out a bit. There is a lot of code here, but that is because a lot needs to be done to format the data into something we want to see.

The desired result:

So, let’s see all that code:

The XAML:


<Window x:Class="GetProcessCountLegacy.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="525">

    <Window.Resources>

        <!-- Text Styles -->
        <Style x:Key="ListHeader" TargetType="{x:Type TextBlock}">
            <Setter Property="FontWeight" Value="Bold" />
        </Style>
        <Style x:Key="ListLabel" TargetType="{x:Type TextBlock}">
            <Setter Property="FontWeight" Value="Normal" />
        </Style>
        <Style x:Key="ListValue" TargetType="{x:Type TextBlock}">
            <Setter Property="FontWeight" Value="DemiBold" />
        </Style>

        <!-- Border -->
        <Style x:Key="BorderStyle" TargetType="Border">
            <Setter Property="BorderBrush" Value="#999" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="CornerRadius" Value="6" />
            <Setter Property="Padding" Value="16,14,16,16" />
            <Setter Property="Margin" Value="12,6,12,6" />
            <Setter Property="Background">
                <Setter.Value>
                    <LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1.0">
                        <GradientStop Color="#FFFFFF" Offset="0" />
                        <GradientStop Color="#FFFFFF" Offset="0.5" />
                        <GradientStop Color="#EDEDED" Offset="1" />
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid>
        <!-- Processor Information -->
        <Border Style="{StaticResource BorderStyle}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="28"/>
                    <RowDefinition Height="22"/>
                    <RowDefinition Height="22"/>
                    <RowDefinition Height="22"/>
                    <RowDefinition Height="22"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="120"/>
                    <ColumnDefinition Width="600"/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
                                       VerticalAlignment="Top"
                                       Text="Processor Information"
                                       Style="{StaticResource ListHeader}" />

                <TextBlock Grid.Row="1" Grid.Column="0"
                                       Text="Description:"
                                       Style="{StaticResource ListLabel}" />
                <TextBlock Grid.Row="1" Grid.Column="1"
                                       x:Name="txtDescription"
                                       Style="{StaticResource ListValue}" />

                <TextBlock Grid.Row="2" Grid.Column="0"
                                       Text="Core Speed:"
                                       Style="{StaticResource ListLabel}" />
                <TextBlock Grid.Row="2" Grid.Column="1"
                                       x:Name="txtSpeed"
                                       Style="{StaticResource ListValue}" />

                <TextBlock Grid.Row="3" Grid.Column="0"
                                       Text="Count:"
                                       Style="{StaticResource ListLabel}" />
                <TextBlock Grid.Row="3" Grid.Column="1"
                                       x:Name="txtCount"
                                       Style="{StaticResource ListValue}" />

                <TextBlock Grid.Row="4" Grid.Column="0"
                                       Text="Width:"
                                       Style="{StaticResource ListLabel}" />
                <TextBlock Grid.Row="4" Grid.Column="1"
                                       x:Name="txtWidth"
                                       Style="{StaticResource ListValue}" />
            </Grid>
        </Border>
    </Grid>
</Window>

C#

[Main Code]


    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Contructors

        /// <summary>
        /// Main constructor.
        /// </summary>
        public MainWindow()
        {
            // Initialize UI
            InitializeComponent();

            // Get processor information
            GetProcessorInformation();
        }

        #endregion

        /// <summary>
        /// Retrieve the processor information and add to UI.
        /// </summary>
        private void GetProcessorInformation()
        {
            // Build an options object for the remote connection
            var options = new ConnectionOptions
                {
                    Impersonation = ImpersonationLevel.Impersonate,
                    EnablePrivileges = true
                };

            // Make a connection to a remote computer.
            var ms = new ManagementScope(@"" + "." + @"rootcimv2", options);

            // Query
            string query = "SELECT Manufacturer, MaxClockSpeed, AddressWidth, Name, " +
                           "SocketDesignation, ProcessorID, UniqueID FROM Win32_Processor";

            // Searcher
            var searcher =
                new ManagementObjectSearcher(ms, new WqlObjectQuery(query));

            // Get legacy info
            var processor = GetProcessorInfoLegacy(searcher);

            // Processor information
            // Description
            txtDescription.Text = RemoveExcessSpaces(processor.Name);
            if (String.IsNullOrEmpty(txtDescription.Text))
            {
                txtDescription.Text = "{Unknown}";
            }

            // Speed
            txtSpeed.Text = GetProcessorSpeed(processor.Speed);
            if (String.IsNullOrEmpty(txtSpeed.Text))
            {
                txtSpeed.Text = "{Unknown}";
            }

            // Count
            txtCount.Text = GetProcessorCount(5.2, processor);
            if (String.IsNullOrEmpty(txtCount.Text))
            {
                txtCount.Text = "{Unknown}";
            }

            // Width
            txtWidth.Text = "x86-" + processor.Architecture;
            if (String.IsNullOrEmpty(txtWidth.Text))
            {
                txtWidth.Text = "{Unknown}";
            }
        }

        /// <summary>
        /// Gets processor information for Windows version 5.x.
        /// </summary>
        /// <param name="searcher"></param>
        /// <returns></returns>
        private static ProcessorInfo GetProcessorInfoLegacy(
            ManagementObjectSearcher searcher)
        {
            // Processor object
            var processor = new ProcessorInfo();

            // Descriptors
            var socket = new List<string>();
            var procId = new List<string>();
            var uniqueId = new List<string>();

            // Get data
            ManagementObjectCollection colItems = searcher.Get();

            try
            {
                // Evaluate data
                foreach (ManagementBaseObject objItem in colItems)
                {
                    // Manufacturer
                    if (objItem["Manufacturer"] != null)
                    {
                        processor.Manufacturer = objItem["Manufacturer"].ToString();
                    }

                    // Speed
                    if (objItem["MaxClockSpeed"] != null)
                    {
                        processor.Speed = Convert.ToInt32(objItem["MaxClockSpeed"]);
                    }

                    // Architecture
                    if (objItem["AddressWidth"] != null)
                    {
                        processor.Architecture = objItem["AddressWidth"].ToString();
                    }

                    // Socket Designation
                    if (objItem["SocketDesignation"] != null)
                    {
                        processor.SocketDesignation =
                            objItem["SocketDesignation"].ToString();
                        socket.Add(processor.SocketDesignation);
                    }

                    // Name
                    if (objItem["Name"] != null)
                    {
                        processor.Name = objItem["Name"].ToString();
                    }

                    // ProcessorID
                    if (objItem["ProcessorID"] != null)
                    {
                        processor.ProcessorID = objItem["ProcessorID"].ToString();
                        procId.Add(processor.ProcessorID);
                    }
                    else
                    {
                        procId.Add("");
                    }

                    // UniqueID
                    if (objItem["UniqueID"] != null)
                    {
                        processor.UniqueID = objItem["UniqueID"].ToString();
                        uniqueId.Add(processor.UniqueID);
                    }
                    else
                    {
                        uniqueId.Add("");
                    }
                }

                // Logical count
                int totalProcCount = colItems.Count;
                processor.LogicalProcessors = totalProcCount;

                // Cores
                GetLegacyCoreCount(socket, procId, uniqueId, ref processor);

                // Get #of possible sockets
                if ((processor.Cores > 0) && (processor.LogicalProcessors > 0))
                {
                    int result = (processor.LogicalProcessors / processor.Cores);
                    processor.Count = result;
                }
            }
            catch
            {
            }
            finally
            {
                colItems.Dispose();
            }

            // return
            return processor;
        }

        /// <summary>
        /// Gets the number of processor cores for Windows version 5.x.
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="procId"></param>
        /// <param name="uniqueId"></param>
        /// <param name="processor"></param>
        private static void GetLegacyCoreCount(List<string> socket, List<string> procId,
                                               List<string> uniqueId, ref ProcessorInfo processor)
        {
            int totalProcessors = 0;

            // Processor marker

            // Check Socket Designation
            for (int i = 0; i < socket.Count; i++)
            {
                // Start with the assumption this is unique.
                bool isUnique = true;

                // Check for Redundancies
                for (int j = i + 1; j < socket.Count; j++)
                {
                    if (socket[i] == socket[j])
                    {
                        isUnique = false;
                        break;
                    }
                }

                // If Redundant Unique ID's Exist
                for (int j = i + 1; j < socket.Count; j++)
                {
                    if ((uniqueId[i] != "") && (uniqueId[j] != "") &&
                        (uniqueId[i] != uniqueId[j]))
                    {
                        isUnique = true;
                        break;
                    }
                }

                // Check for NULL ProcessorID
                if (procId[i].Trim() == "0000000000000000")
                {
                    isUnique = false;
                }

                // Calculate Total
                if (isUnique)
                {
                    totalProcessors++;
                }
            }

            // Get Cores
            int result = (processor.LogicalProcessors / totalProcessors);
            processor.Cores = result;
        }

        /// <summary>
        /// Retrieves the Processor speed in human-readable format.
        /// </summary>
        /// <param name="speed"></param>
        /// <returns></returns>
        public static string GetProcessorSpeed(int speed)
        {
            string result = string.Empty;

            if (speed.ToString().Length >= 4)
            {
                double dSpeed = Convert.ToDouble(speed) / 1000;
                result = dSpeed.ToString("0.00") + " GHz";
            }
            else
            {
                result = speed.ToString() + " MHz";
            }

            // Return
            return result;
        }

        /// <summary>
        /// Returns the processor count in a human-readable format.
        /// </summary>
        /// <param name="oSver"></param>
        /// <param name="proc"></param>
        /// <returns></returns>
        public static string GetProcessorCount(double oSver, ProcessorInfo proc)
        {
            string result = "";

            int physical = proc.Count;
            int cores = proc.Cores;

            // Manufacturer
            string hyper = "HyperThreading";
            if (proc.Manufacturer.ToLower().IndexOf("intel") == -1)
            {
                hyper = "HyperTransport";
            }

            // Processor count
            string physDesc = physical.ToString() + " processor(s)";

            // Cores
            string coreDesc = string.Empty;

            // Current
            if (oSver >= 6)
            {
                coreDesc = cores.ToString() + " core(s)";
                if (proc.IsHyperThreaded)
                {
                    coreDesc += " w/ HyperThreading";
                }
            }

                // Legacy
            else
            {
                coreDesc = cores.ToString() + " core(s)";

                if ((cores / physical) == 2)
                {
                    // Intel
                    if (proc.Manufacturer.ToLower().IndexOf("intel") != -1)
                    {
                        coreDesc += " (or " + physical + " core(s) w/ " + hyper + ")";
                    }
                }
            }

            result = physDesc + " (" + coreDesc + ")";

            // Return
            return result;
        }

        /// <summary>
        /// Removes extra spaces between words.
        /// </summary>
        /// <param name="procDesc"></param>
        /// <returns></returns>
        public static string RemoveExcessSpaces(string procDesc)
        {
            string result = "";

            // Evaluate
            string[] desc = procDesc.Split((char)32);

            // Name
            for (int i = 0; i < desc.Length; i++)
            {
                if (desc[i].Trim() != "")
                {
                    result += desc[i] + " ";
                }
            }

            // Return
            return result;
        }
    }

[ProcessorInfo class]


    /// <summary>
    /// Information relevant to the physical processors.
    /// </summary>
    public class ProcessorInfo
    {
        #region Properties

        /// <summary>
        /// Win32_Processor: AddressWidth: On a 32-bit operating system, the value is 32
        /// and on a 64-bit operating system it is 64.
        /// </summary>
        public string Architecture { get; set; }

        /// <summary>
        /// Win32_Processor: NumberOfCores: Number of cores for the current instance of
        /// the processor.
        /// </summary>
        public int Cores { get; set; }

        /// <summary>
        /// Total processor count.
        /// </summary>
        public int Count { get; set; }

        /// <summary>
        /// Determines whether processors support Hyper-Threading or Hyper-Transport.
        /// </summary>
        public bool IsHyperThreaded { get; set; }

        /// <summary>
        /// Win32_Processor: NumberOfLogicalProcessors: Number of logical processors for
        /// the current instance of the processor.
        /// </summary>
        public int LogicalProcessors { get; set; }

        /// <summary>
        /// Win32_Processor: Manufacturer: Name of the processor manufacturer.
        /// </summary>
        public string Manufacturer { get; set; }

        /// <summary>
        /// Win32_Processor: Name: Label by which the object is known.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Win32_Processor: ProcessorID: Processor information that describes the
        /// processor features.
        /// </summary>
        public string ProcessorID { get; set; }

        /// <summary>
        /// Win32_Processor: SocketDesignation: Type of chip socket used on the circuit.
        /// </summary>
        public string SocketDesignation { get; set; }

        /// <summary>
        /// Win32_Processor: MaxClockSpeed: Detected processor speed.
        /// </summary>
        public int Speed { get; set; }

        /// <summary>
        /// Win32_Processor: UniqueID: Globally unique identifier for the processor.
        /// </summary>
        public string UniqueID { get; set; }

        #endregion

        #region Constructors

        public ProcessorInfo()
        {
            Architecture = "x86";
        }

        #endregion
    }