Find CPU CORE using WMI query - wmi-query

I want to list out the CPU Core / Processes in the system. When I have used select DeviceID from Win32_Processor, I got CPU0 as result; But I am expecting result as "CPU0,CPU1,CPU2,CPU3" since there are multiple cores. Is there any other one liner available for finding out this?
Thanking you...

I know this is old , but for others searching , Win32_Processor it contains, NumberOfCores and NumberOfLogicalProcessors

Related

System.Diagnostics.PerformanceCounter current CPU usage in GHz

I need the information of the current CPU usage in GHz as the Task Manager shows is under Performance in the Speed variable.
Is it possible to get this information from the method?
I need it in Matlab by the way.
I was hoping to use this function for it:
Show CPU cores utilization in MATLAB
Thanks.
So, the answer is:
obj = System.Diagnostics.PerformanceCounter('Processor Information', '% Processor Performance', '_Total');
current_frequency = obj.NextValue * base_frequency;

Unable to get current CPU frequency in Powershell or Python

I am trying to somehow programamtically log the CPU frequency of my windows 10 machine. However I apparently fail to get the current frequency as shown in the task manager.
in Powershell, using
get-wmiobject Win32_Processor -Property CurrentClockSpeed
does only return a clock speed that is exactly the maximum one (even though i can see in task manager that it is not running that high)
I even tried this solution: https://www.remkoweijnen.nl/blog/2014/07/18/get-actual-cpu-clock-speed-powershell/ but it did not give me anything but a static value = max value.
Even python's psutil does only return a static value.
Does anybody know how to get around this and actually somehow log the CPU frequency each x seconds?
any help would be appreciated, thanks!
TLDR: To find the Current Processor Frequency, you have to use the % Processor Performance performance counter:
$MaxClockSpeed = (Get-CimInstance CIM_Processor).MaxClockSpeed
$ProcessorPerformance = (Get-Counter -Counter "\Processor Information(_Total)\% Processor Performance").CounterSamples.CookedValue
$CurrentClockSpeed = $MaxClockSpeed*($ProcessorPerformance/100)
Write-Host "Current Processor Speed: " -ForegroundColor Yellow -NoNewLine
Write-Host $CurrentClockSpeed
The more in depth explanation as to why does querying WMI Win32_Processor for CurrentClockSpeed seem to always return the maximum frequency rather than the actual "Current Clock Speed"? In fact, why do all of the dozens of WMI/CMI/Perfmon counters all seem to return the "wrong" frequency? If CPU-Z and Task Manager can get it, what do we have to do to get the "actual" frequency? To answer that, we need to understand what CurrentClockSpeed is actually returning.
From the WMI documentation for Win32_Processor CurrentClockSpeed:
Current speed of the processor, in MHz. This value comes from the
Current Speed member of the Processor Information structure in the
SMBIOS information.
Great! One would think that this simple query should get us the current frequency. This worked great a dozen years ago, but nowadays it doesn't; because it really only works for two very specific cases:
When you have a processor that only runs at its defined stock speed.
When a mobile processor is asked by Windows to run at a different speed (e.g. moving to battery mode).
At startup, Widows gets the processor information and gets the Current Clock Speed. Most people are running their processor at the recommended settings so Current Clock Speed == Max Clock Speed, which mean that the two numbers match all the time. When you change power states, Windows will change the frequency, and CurrentClockSpeed will be changed as well.
Now, what happened a dozen years ago to essentially make CurrentClockSpeed completely inaccurate/irrelevant? You can ultimately thank Intel. They essentially blew this whole ideal value out of the water thanks to a new technology called Turbo Boost.
What does Turbo Boost have to do with this?
Turbo Boost dynamically changes the processor frequency based on the current load on the processor within the confines of voltage, current, and thermal envelopes. Almost all modern processors also now have power saving modes and can dynamically change their frequencies based on their current marketing buzzword (e.g. Turbo Boost (up), Cool'N'Quiet (down)).
The key point is: all this frequency moving up/down/off/on is all automatically done without Windows knowing about it. Because Windows doesn't know about it, the CurrentClockSpeed value could be completely inaccurate most of the time. In fact, Microsoft knows this, and when you open your Performance Monitor, and you look at the description under Processor Performance/Processor Frequency:
Processor Frequency is the frequency of the current processor in
megahertz. Some processors are capable of regulating their frequency
outside of the control of Windows. Processor Frequency will not
accurately reflect actual processor frequency on these systems. Use
Processor Information\% Processor Performance instead.
Fortunately this description gives us a hint of what we have to use to get the actual value: Processor Information\% Processor Performance
We can use Get-Counter to access the current Processor performance like so:
PS C:\> Get-Counter -Counter "\Processor Information(_Total)\% Processor Performance"
Timestamp CounterSamples
--------- --------------
2020-01-01 1:23:45 AM \\HAL9256\processor information(_total)\% processor performance :
153.697654229441
Here, you can see that my processor is running at 153% performance a.k.a. 153% of the frequency of the processor (yay for Turbo Boost!). We then query the MaxClockSpeed from CIM_Processor class (you can use WMI_Processor as well):
PS C:\> (Get-CimInstance CIM_Processor).MaxClockSpeed
2592
In order to calculate out the actual clock speed:
$MaxClockSpeed = (Get-CimInstance CIM_Processor).MaxClockSpeed
$ProcessorPerformance = (Get-Counter -Counter "\Processor Information(_Total)\% Processor Performance").CounterSamples.CookedValue
$CurrentClockSpeed = $MaxClockSpeed*($ProcessorPerformance/100)
Write-Host "Current Processor Speed: " -ForegroundColor Yellow -NoNewLine
Write-Host $CurrentClockSpeed
Then wrapping it up in a loop if you need it to run every 2 seconds (Ctrl+C to stop):
$MaxClockSpeed = (Get-CimInstance CIM_Processor).MaxClockSpeed
While($true){
$ProcessorPerformance = (Get-Counter -Counter "\Processor Information(_Total)\% Processor Performance").CounterSamples.CookedValue
$CurrentClockSpeed = $MaxClockSpeed*($ProcessorPerformance/100)
Write-Host "Current Processor Speed: " -ForegroundColor Yellow -NoNewLine
Write-Host $CurrentClockSpeed
Sleep -Seconds 2
}
With help of the PS code above and the doc of win32pdh, I'm able to get it work in Python:
from win32pdh import PDH_FMT_DOUBLE
from win32pdh import OpenQuery, CloseQuery, AddCounter
from win32pdh import CollectQueryData, GetFormattedCounterValue
def get_freq():
ncores = 16
paths = []
counter_handles = []
query_handle = OpenQuery()
for i in range(ncores):
paths.append("\Processor Information(0,{:d})\% Processor Performance".format(i))
counter_handles.append(AddCounter(query_handle, paths[i]))
CollectQueryData(query_handle)
time.sleep(1)
CollectQueryData(query_handle)
freq = []
for i in range(ncores):
(counter_type, value) = GetFormattedCounterValue(counter_handles[i], PDH_FMT_DOUBLE)
freq.append(value*2.496/100)
# 2.496 is my base speed, I didn't spend time to automate this part
# print("{:.3f} Ghz".format(max(freq)))
CloseQuery(query_handle)
return "{:.3f} GHz".format(max(freq))

How I know if CPU is Haswell or Not

You know, haswell is the codename for a processor microarchitecture developed by Intel as the "fourth-generation core" successor to the Ivy Bridge microarchitecture.1 Intel officially announced CPUs based on this microarchitecture... More
But, I want to know how to show's up my CPU if haswell or not by using the PowerShell in windows?
in this case i have a script to to that, but it maybe not legal for everyone:
$cpuname = (Get-CimInstance CIM_Processor).Name
$splcpuall = #($cpuname -csplit "")
$splcpu = $splcpuall[20]
$ishaswell = if ($splcpu -gt 3){
Write-Output "Haswell"
}
Identifying a CPU needs some digging and regular maintenance for new CPU models is needed too. Your best bet is to use some existing tool that provides CPU information. For example, CPU-Z is nice a tool.
The problem is that CPUs don't contain human readable name strings. What they contain is a CPUID, a hex code that must be looked up and interpreted as model name. Hashwell's ID is 0x0306C3, Broadwell's is 0x0306D4 and so on.
Digging up the CPUID can be done via WMI. On a Broadwell box:
(gwmi win32_processor).ProcessorId
BFEBFBFF000306D4
The result is a string combination that contains stuff in addition to the CPU ID. This needs to be parsed to identify the CPU ID part and then the matched name must be looked up from somewhere.

How do I get hardware info such as CPU name, total RAM, etc. with VB6?

Title pretty much explains it all. I need to get some hardware information such as CPU info, and total RAM with VB6. Ideally, it would return something like this for the CPU:
Intel Core 2 Quad Q8500 2.66 GHz
and for the RAM something simple like an integer for the amount of MB the computer has total.
in plain C, if interested:
#include <intrin.h>
int cpuInfo[4] = {-1};
char CPUBrandString[0x40];
memset(CPUBrandString, 0, sizeof(CPUBrandString));
__cpuid(cpuInfo, 0x80000002);
memcpy(CPUBrandString, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000003);
memcpy(CPUBrandString + 16, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000004);
memcpy(CPUBrandString + 32, cpuInfo, sizeof(cpuInfo));
You could use WMI to get this information:
http://msdn.microsoft.com/en-us/library/aa394084(v=VS.85).aspx
This information is also available in the registry (if WMI isn't to your liking):
HKLM/HARDWARE/DESCRIPTION/System/CentralProcessor
NOTE: Registry keys and locations may change. The WMI API is designed as a more stable source for this kind of information.
RAM - GetPhysicallyInstalledSystemMemory (GlobalMemoryStatusEx on earlier versions)
CPU - GetSystemInfo (not in the desired friendly form, I'm afraid). There is a very extensive discussion of more detailed CPU info retrieval here.

How can I find the exact amount of physical memory on Windows x86-32bit using Perl or any other language?

I need to know how much physical memory a windows machine has, using Perl.
I've tried using Win32::SystemInfo. However this module states the following caveat:
On Intel x86 computers with more than 2 GB and less than 4 GB of memory, the MemoryStatus function will always return 2 GB for TotalPhys. Similarly, if the total available memory is between 2 and 4 GB, AvailPhys will be rounded down to 2 GB.
So on a machine which has 2-4 GB of physical memory, I get a false answer.
Is there a way to get the correct amount of physical memory? Perhaps another module? Or directly using Win32::API?
Edit: From the comments people gave here, it looks like the limitation is in the Win32 API , and not specific to Win32::SystemInfo. However, the OS does know exactly how much physical ram is available, so there must be a way to extract that information. If not in Perl then maybe in another language?
As stated in the comments, this is an issue of GlobalMemoryStatus, as it can return answers up to 2GB. And GlobalMemoryStatusEX which solves this issue of the 2GB limit, but only works on 64 bit systems (as far as I can tell).
In the end I'm using the following Perl code, which uses Win32::OLE and WMI class Win32_PhysicalMemory, which returns the correct amount of physical memory even on 32bit systems:
use strict;
use warnings;
use English;
use Win32::OLE qw( EVENTS HRESULT in );
use Readonly;
sub get_physical_memory {
my $machine = shift || '.'; # Default to local machine
my Readonly $WMI_MEMORY_CLASS_NAME = 'Win32_PhysicalMemory';
my Readonly $MEGABYTE = 1024*1024;
my $WMI =
Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//$machine/" ) || die "Could not get Win32 object: $OS_ERROR";
my $total_capacity = 0;
foreach my $object ( in( $WMI->InstancesOf( $WMI_MEMORY_CLASS_NAME ) ) ) {
$total_capacity += $object->{Capacity};
}
my $total_capacity_in_mb = $total_capacity / $MEGABYTE;
print "Total Memory : $total_capacity_in_mb \n";
return $total_capacity_in_mb;
}
I can only assume that the caveats attending Win32::SystemInfo's results are also caveats attending the raw Win32 API calls, as Perl itself certainly has no problem handling such large numbers. In which case the possibility of extracting accurate information looks a bit bleak.
I've also heard in passing that current 32-bit versions of Windows can only use about 3.2Gb of RAM on a machine that has >= 4Gb installed, which may be hearsay, but which jibes with the limitation being in the API itself.
This information can be pulled from WMI, or using SNMP if you choose to enable SNMP on the box it will be running on. For WMI, I don't have a Perl example offhand but for a VBScript example see below.
Ref: http://www.microsoft.com/technet/scriptcenter/guide/sas_wmi_dieu.mspx
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer)
Set colSWbemObjectSet = _
objSWbemServices.InstancesOf("Win32_LogicalMemoryConfiguration")
For Each objSWbemObject In colSWbemObjectSet
Wscript.Echo "Total Physical Memory (kb): " & _
objSWbemObject.TotalPhysicalMemory
Next
Tested on my XP system and it retrieves the desired results (only 1.5GB RAM here, sorry). I'm quite sure there are WMI interfaces for Perl as well if you want to stick with Perl. If SNMP is an option, the total physical memory can be obtained from SNMP as well using one of the Perl SNMP libraries.
EDIT: Just noticed #Mr. Muskrat's comment regarding Microsoft KB http://support.microsoft.com/kb/274558 - evidently the behavior you're seeing with Perl is a limitation of the Win32 API call, so you might end up with the same results with WMI. Unfortunately I don't have a 2-4GB RAM machine to try this on to verify.

Resources