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
}
