There are a great number of different ways to count the number of processors available to the .NET developer. In this post I will go over some of the more common methods and their pros and cons.
 

The Envirionment.ProcessorCount Way

Code:

Environment.ProcessorCount;

 

Supported Platforms:

Windows 98 Or Greater, .NET 2.0 or Greater

Pros:

  • Easiest Method
  • Value Cannot be Changed by The User
  • No External Calls (All .NET)

Cons:

  • .NET 1.1 Incompatible
  • Logical CPU Count Only

Misc:

  • Counts Each Core
  • Counts Hyperthreaded Cpus As 2

Notes:

For more information check out the MSDN site for this property is here.

 

The Environment Variable Way

Code:

String strProcs =
  System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");
uint numProcs;
if (!UInt32.TryParse(strProcs, out numProcs))
  numProcs = 1;
 
Unfortunately, changing the value is as easy as:

System.Environment.SetEnvironmentVariable("NUMBER_OF_PROCESSORS", "3");

 

Supported Platforms:

NT4 or Greater

Pros:

  • Fast And Easy
  • Easy To Change Value For Testing
  • No External Calls (All .NET)

Cons:

  • Easy For User To Change
  • Logical CPU Count Only

Misc:

  • Counts Each Core
  • Counts Hyperthreaded Cpus As 2
 

The System.Mangement (WMI) Way

Code:           

SelectQuery query = new SelectQuery("Win32_ComputerSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection collection = searcher.Get();
UInt32 procs;
UInt32 nop = 0, nlp = 0;
foreach (ManagementObject obj in collection)
{
    nop = (UInt32)obj["NumberOfProcessors"];
    try
    {
        nlp = (UInt32)obj["NumberOfLogicalProcessors"];
    }
    catch (ManagementException E)
    {
        nlp = 0;
    }
}
procs = nop > nlp ? nop : nlp; 

 

Supported Platforms: 

2000 or Greater, .NET 1.1 or Greater

Pros:

  • No External Calls (All .NET)
  • Value Cannot be Changed by The User
  • Some Extended Information is Available
  • Differentiates Between Hyperthreaded and Actual Cores in Vista.

Cons:

  • Requires the System.Management Assembly
  • Somewhat Complex

Misc:

  • Counts Each Core
  • Pre-Vista Counts Hyperthreaded Cpus As 2

Notes:

NumberOfLogicalProcessors is new in Vista. The only difference in comparison to NumberOfProcessors is that hyperthreaded processors count as two each. If you would like support for NumberOfLogicalProcessors and several other new WMI objects in XP and 2003 Microsoft has a patch available:
XP: http://support.microsoft.com/kb/936235/
2003: http://support.microsoft.com/kb/932370/
 
For more detailed information about the new WMI features in Vista (and with this patch)  check out the this article on Juice:
 
 

The Kernel32 Way

Code:

public class WinApi
{
    [DllImport("kernel32.dll")]
    public static extern void GetSystemInfo([MarshalAs(UnmanagedType.Struct)] ref SYSTEM_INFO lpSystemInfo);
 
    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEM_INFO
    {
        internal _PROCESSOR_INFO_UNION uProcessorInfo;
        public uint dwPageSize;
        public IntPtr lpMinimumApplicationAddress;
        public IntPtr lpMaximumApplicationAddress;
        public IntPtr dwActiveProcessorMask;
        public uint dwNumberOfProcessors;
        public uint dwProcessorType;
        public uint dwAllocationGranularity;
        public ushort dwProcessorLevel;
        public ushort dwProcessorRevision;
    }
 
    [StructLayout(LayoutKind.Explicit)]
    public struct _PROCESSOR_INFO_UNION
    {
        [FieldOffset(0)]
        internal uint dwOemId;
        [FieldOffset(0)]
        internal ushort wProcessorArchitecture;
        [FieldOffset(2)]
        internal ushort wReserved;
    }
}
 

 
WinApi.SYSTEM_INFO sysinfo = new WinApi.SYSTEM_INFO();
WinApi.GetSystemInfo(ref sysinfo);
uint procs = sysinfo.dwNumberOfProcessors; 

 

Supported Platforms:

9x, NT, 2000, 2003, XP, Vista, 2008

Pros:

  • Best Legacy Support
  • Value Cannot be Changed by the User
  • Additional Detailed Processor Information is Available

Cons:

  • External Calls to Kernel32.dll
  • Requires a Bunch of Extra Code

Misc:

  • Counts Each Core
  • Counts Hyperthreaded Cpus as Two

Notes:

Intel has an article on using this technique to deternine number of cores and hyperthreading here.
PInvoke.NET has a fairly comprehensive article on using this technique here.
 
 

The GetLogicalProcessorInformation Way

Code:

An example is not provided because I currently am running Windows XP 32-Bit and was unable to find a reasonable example. This method is mentioned here for completeness only.

 

Supported Platforms:

XP SP3, XP x64 Pro, 2003, 2008

Pros:

  • Gives the Most Detailed Information Available
  • Can Deternime Number of Cores and Hyperthreading for Each Processor

Cons: 

  • External Calls to Kernel32.dll
  • Requires a Bunch of Extra Code
  • Very New Platform Support Only
  • Documentation is C++ Only
  • Almost All of the Same Information is Available Through the WMI Interface.

Misc:

Can Deternime Number of Cores and Hyperthreading for Each Processor

Notes:

You can view Microsoft’s MSDN Article on this method here.

 

Other Methods

There are a couple of other methods I am aware of but didn’t explicitly list:
You can look in the Registry at:
HKEY_LOCAL_MACHINE\Hardware\
Description\System\CentralProcessor
And count the number of children. However, this is still counting logical processors.
 
Intel as an interesting series of articles on using some ASM calls to deternine anything you might want know about the CPUs on a computer. You can find them here.
 
I also found an interesting Code Project article which uses a lot of backend ASM. It can determine the number of actual cpus, logical cpus and hyperthreading support. I can’t vouch for it’s safety but you can find it here.