Jump to content

Getting system CPU info


Rishodi
 Share

Recommended Posts

I need a way to pull information about the CPU(s) in the system on which I run my script. I've been using CompInfo.au3 for a couple of years now, but this is the first time that I've had significant trouble with it. Using the _ComputerGetProcessors function to pull data from the WMI Win32_Processor class has always worked in the past, but no longer.

The workstation I'm testing my script on has an Intel Core 2 Duo T9400. However, a query of all Win32_Processor objects returns only a single object with the name "Intel Pentium III Xeon processor". Of course, that's quite wrong, though some of the other information appears correctly, such as the clock speed and L2 cache size. I haven't found anything useful in Microsoft's WMI documentation yet. How can I get the correct processor information?

Link to comment
Share on other sites

You'll get that return because WMI doesn't know about the newer processors. It's reading the processor info and it must be returning the value of 176, which to the Win32_processor function, that means it's a Xeon P3. Unless Microsoft updates the returns for the newer CPUs or the manufacturers of the CPUs use different architecture codes, it won't change.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

This works on my 2008R2...not very efficient though

TraySetState()

#include <Misc.au3>
_Singleton(@ScriptName, 0)

Global $wTitle = '[REGEXPTITLE:(?i)System Information; CLASS:#32770]', $Item, $Text

If Not ProcessExists('msinfo32.exe') Then Run('msinfo32.exe', '', @SW_HIDE)
WinWait($wTitle, '')
$hWindow = WinGetHandle($wTitle, '')
WinSetState($hWindow, '', @SW_HIDE)

Do
    $Item = ControlListView($hWindow, '', 'SysListView321', 'FindItem', 'Processor')
Until $Item

Do
    $Text = ControlListView($hWindow, '', 'SysListView321', 'GetText', $Item, 1)
Until $Text

ProcessClose('msinfo32.exe')
MsgBox(32, 'Processor', $Text)

Link to comment
Share on other sites

You'll get that return because WMI doesn't know about the newer processors. It's reading the processor info and it must be returning the value of 176, which to the Win32_processor function, that means it's a Xeon P3. Unless Microsoft updates the returns for the newer CPUs or the manufacturers of the CPUs use different architecture codes, it won't change.

Yes, I presumed that the WMI information is outdated, but why? I know the correct information is somewhere on my system. My CPU shows up correctly in System Properties and Device Manager as Intel Core 2 Duo CPU T9400 @ 2.53 GHz. Shouldn't there be some way to get that information through COM objects?

Download the WMI Code Creator here. Try the Namespace as: "root\CIMV2" and the property as "Description"

EDIT: Make sure that you run "WMICodeCreator.exe" as Administrator

The Description property of the lone Win32_Processor object is this: x86 Family 6 Model 23 Stepping 10. Not very useful, unfortunately.

The processor info given in msinfo32 isn't helpful either. The full text field is x86 Family 6 Model 23 Stepping 10 GenuineIntel ~2527 Mhz, which doesn't give me any information I couldn't get through WMI. Those are the Description, Manufacturer, and CurrentClockSpeed properties in order. ;)

Link to comment
Share on other sites

You'll get that return because WMI doesn't know about the newer processors. It's reading the processor info and it must be returning the value of 176, which to the Win32_processor function, that means it's a Xeon P3. Unless Microsoft updates the returns for the newer CPUs or the manufacturers of the CPUs use different architecture codes, it won't change.

Processor info is stored inside the processor itself, on the lowest possible level. It's retrieved with CPUID instruction.

If WMI fails to get right info then the reason is something else than what you think.

I posted this somewhere already and other posted their versions too (maybe better). Again:

#AutoIt3Wrapper_UseX64=n

#include <Memory.au3>

; Allocating memory with $PAGE_EXECUTE_READWRITE
Global $pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)

; Standard allocation in reserved address
Global $tCodeBuffer = DllStructCreate("byte[512]", $pRemoteCode)


;XXXXXXXXXXXXXX BASIC CALLING PARAMETER XXXXXXXXXXXXXXXXXXXXXXXXXX

ConsoleWrite("! EAX = 0" & @CRLF)

; Buffer to fill with data:
Global $tBuffer = DllStructCreate("char[12]")

; Pointer to it:
Global $pBuffer = DllStructGetPtr($tBuffer)


; Code:
DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _; 10. SET eax AND CALL
        "B8" & SwapEndian(0) & _                                 ; mov eax, 0
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "891D" & SwapEndian($pBuffer) & _                        ; mov dword[$pBuffer], ebx
        "8915" & SwapEndian($pBuffer + 4) & _                    ; mov dword[$pBuffer + 4], edx
        "890D" & SwapEndian($pBuffer + 8) & _                    ; mov dword[$pBuffer + 8], ecx
        "" & _ ; 30. RETURN
        "C3" _
        )

; Execute it:
Global $iRet = _RunAtAddress($pRemoteCode)

; Return:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:

ConsoleWrite("The highest basic calling parameter: " & $iRet & @CRLF)
ConsoleWrite("Vendor ID: " & DllStructGetData($tBuffer, 1) & @CRLF)

ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite("! EAX = 1" & @CRLF)

; New buffer:
$tBuffer = DllStructCreate("dword[4]")

; Pointer to it:
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _ ; 10. SET eax AND CALL
        "B8" & SwapEndian(1) & _                                 ; mov eax, 1
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "A3" & SwapEndian($pBuffer) & _                          ; mov dword[$pBuffer], eax
        "8915" & SwapEndian($pBuffer + 4) & _                    ; mov dword[$pBuffer + 4], edx
        "890D" & SwapEndian($pBuffer + 8) & _                    ; mov dword[$pBuffer + 8], ecx
        "891D" & SwapEndian($pBuffer + 12) & _                   ; mov dword[$pBuffer + 12], ebx
        "" & _ ; 30. RETURN
        "C3" _
        )

; Execute it:
$iRet = _RunAtAddress($pRemoteCode)

; Return eax:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:
ConsoleWrite("EAX: " & DllStructGetData($tBuffer, 1, 1) & @CRLF)
ConsoleWrite("Hyper-Threading Technology: " & BitShift(DllStructGetData($tBuffer, 1, 2), 28) & @CRLF) ; bit 28
ConsoleWrite("ECX (feature flag): " & DllStructGetData($tBuffer, 1, 3) & @CRLF)
ConsoleWrite("EBX (LogicalProcessorCount): " & DllStructGetData($tBuffer, 1, 4) & @CRLF)

ConsoleWrite("+ Derived out of EAX: " & @CRLF)
$iEAX = DllStructGetData($tBuffer, 1, 1)

$iStepping = BitAND($iEAX, 0xF) ; 0-3
ConsoleWrite("    Stepping: " & $iStepping & @CRLF)
$iBaseModel = BitAND(BitShift($iEAX, 4), 0xF) ; 4-7
ConsoleWrite("    BaseModel: " & $iBaseModel & @CRLF)
$iBaseFamily = BitAND(BitShift($iEAX, 8), 0xF) ; 8-11
ConsoleWrite("    BaseFamily: " & $iBaseFamily & @CRLF)
ConsoleWrite("    Reserved: " & BitAND(BitShift($iEAX, 12), 0xF) & @CRLF) ; 12-15
$iExtendedModel = BitAND(BitShift($iEAX, 16), 0xF) ; 16-19
ConsoleWrite("    Extended Model: " & $iExtendedModel & @CRLF)
$iExtendedFamily = BitAND(BitShift($iEAX, 20), 0xFF) ; 20-27
ConsoleWrite("    Extended Family: " & $iExtendedFamily & @CRLF)
ConsoleWrite("    Reserved: " & BitAND(BitShift($iEAX, 28), 0xF) & @CRLF) ; 28-31

ConsoleWrite("+         Derived out of that: " & @CRLF)
ConsoleWrite("               Model: " & "~~" & @CRLF) ;<- needs calculating
ConsoleWrite("               Family: " & "~~" & @CRLF) ;<- needs calculating


ConsoleWrite("+ Derived out of EBX: " & @CRLF)
$iEBX = DllStructGetData($tBuffer, 1, 4)
$iBrandID = BitAND($iEBX, 0xFF) ; 0-7
ConsoleWrite("    Brand ID: " & $iBrandID & @CRLF)
$iCLFLUSH = BitAND(BitShift($iEBX, 8), 0xFF) ; 8-15
ConsoleWrite("    CLFLUSH size: " & $iCLFLUSH & @CRLF)
$iLogicalProcessorCount = BitAND(BitShift($iEBX, 16), 0xFF) ; 16-23
ConsoleWrite("    LogicalProcessorCount: " & $iLogicalProcessorCount & @CRLF)
$LocalApicId = BitAND(BitShift($iEBX, 24), 0xFF) ; 24-32
ConsoleWrite("    LocalApicId: " & $LocalApicId & @CRLF)






ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite("! EAX = 2" & @CRLF); This one is couldn't be tested with me (the highest basic calling parameter returned 1)

; New buffer:
$tBuffer = DllStructCreate("dword[4]")

; Pointer to it:
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _ ; 10. SET eax AND CALL
        "B8" & SwapEndian(2) & _                                 ; mov eax, 2
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "A3" & SwapEndian($pBuffer) & _                          ; mov dword[$pBuffer], eax
        "891D" & SwapEndian($pBuffer + 4) & _                    ; mov dword[$pBuffer + 4], ebx
        "890D" & SwapEndian($pBuffer + 8) & _                    ; mov dword[$pBuffer + 8], ecx
        "8915" & SwapEndian($pBuffer + 12) & _                   ; mov dword[$pBuffer + 12], edx
        "" & _ ; 30. RETURN
        "C3" _
        )

; Execute it:
$iRet = _RunAtAddress($pRemoteCode)

; Return eax:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:
ConsoleWrite("EAX: " & DllStructGetData($tBuffer, 1, 1) & @CRLF)
ConsoleWrite("EBX: " & DllStructGetData($tBuffer, 1, 2) & @CRLF)
ConsoleWrite("ECX: " & DllStructGetData($tBuffer, 1, 3) & @CRLF)
ConsoleWrite("EDX: " & DllStructGetData($tBuffer, 1, 4) & @CRLF)



; ...etc, depending on he highest basic calling parameter




;XXXXXXXXXXXXXX EXTENDED CALLING PARAMETER XXXXXXXXXXXXXXXXXXXXXXXXXX


ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite("! EAX = 0x80000000" & @CRLF)

; New buffer:
$tBuffer = DllStructCreate("dword[4]")

; Pointer to it:
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _ ; 10. SET eax AND CALL
        "B8" & SwapEndian(0x80000000) & _                        ; mov eax, 0x80000000
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "A3" & SwapEndian($pBuffer) & _                          ; mov dword[$pBuffer], eax
        "" & _ ; 30. RETURN
        "C3" _
        )

; Execute it:
$iRet = _RunAtAddress($pRemoteCode)

; Return eax:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:
ConsoleWrite("The highest extended calling parameter: " & Ptr(DllStructGetData($tBuffer, 1, 1)) & @CRLF)


ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite("! EAX = 0x80000001" & @CRLF)

; New buffer:
$tBuffer = DllStructCreate("dword[4]")

; Pointer to it:
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _ ; 10. SET eax AND CALL
        "B8" & SwapEndian(0x80000001) & _                        ; mov eax, 0x80000001
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "A3" & SwapEndian($pBuffer) & _                          ; mov dword[$pBuffer], eax
        "891D" & SwapEndian($pBuffer + 4) & _                    ; mov dword[$pBuffer + 4], ebx
        "890D" & SwapEndian($pBuffer + 8) & _                    ; mov dword[$pBuffer + 8], ecx
        "8915" & SwapEndian($pBuffer + 12) & _                   ; mov dword[$pBuffer + 12], edx
        "" & _ ; 30. RETURN
        "C3" _
        )

; Execute it:
$iRet = _RunAtAddress($pRemoteCode)

; Return eax:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:
ConsoleWrite("Extended feature flags EAX : " & DllStructGetData($tBuffer, 1, 1) & @CRLF)
ConsoleWrite("Extended feature flags EBX : " & DllStructGetData($tBuffer, 1, 2) & @CRLF)
ConsoleWrite("Extended feature flags ECX (CmpLegacy) : " & DllStructGetData($tBuffer, 1, 3) & @CRLF)
ConsoleWrite("Extended feature flags EDX: " & DllStructGetData($tBuffer, 1, 4) & @CRLF)


ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite("! EAX = 0x80000002->0x80000003->0x80000004" & @CRLF)

; New buffer:
$tBuffer = DllStructCreate("char[48]")

; Pointer to it:
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _ ; 10. SET eax AND CALL
        "B8" & SwapEndian(0x80000002) & _                        ; mov eax, 0x80000002
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "A3" & SwapEndian($pBuffer) & _                          ; mov dword[$pBuffer], eax
        "891D" & SwapEndian($pBuffer + 4) & _                    ; mov dword[$pBuffer + 4], ebx
        "890D" & SwapEndian($pBuffer + 8) & _                    ; mov dword[$pBuffer + 8], ecx
        "8915" & SwapEndian($pBuffer + 12) & _                   ; mov dword[$pBuffer + 12], edx
        "" & _ ; 30. SET eax AND CALL
        "B8" & SwapEndian(0x80000003) & _                        ; mov eax, 0x80000003
        "0FA2" & _                                               ; cpuid
        "" & _ ; 40. ARRANGE DATA
        "A3" & SwapEndian($pBuffer + 16) & _                     ; mov dword[$pBuffer + 16], eax
        "891D" & SwapEndian($pBuffer + 20) & _                   ; mov dword[$pBuffer + 20], ebx
        "890D" & SwapEndian($pBuffer + 24) & _                   ; mov dword[$pBuffer + 24], ecx
        "8915" & SwapEndian($pBuffer + 28) & _                   ; mov dword[$pBuffer + 28], edx
        "" & _ ; 50. SET eax AND CALL
        "B8" & SwapEndian(0x80000004) & _                        ; mov eax, 0x80000004
        "0FA2" & _                                               ; cpuid
        "" & _ ; 60. ARRANGE DATA
        "A3" & SwapEndian($pBuffer + 32) & _                     ; mov dword[$pBuffer + 32], eax
        "891D" & SwapEndian($pBuffer + 36) & _                   ; mov dword[$pBuffer + 36], ebx
        "890D" & SwapEndian($pBuffer + 40) & _                   ; mov dword[$pBuffer + 40], ecx
        "8915" & SwapEndian($pBuffer + 44) & _                   ; mov dword[$pBuffer + 44], edx
        "" & _ ; 70. RETURN
        "C3" _
        )

; Execute it:
$iRet = _RunAtAddress($pRemoteCode)

; Return eax:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:
ConsoleWrite("Processor brand string: " & DllStructGetData($tBuffer, 1) & @CRLF)


MsgBox(0, '', DllStructGetData($tBuffer, 1))


; And so on...

; Just one more:
ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite("! EAX = 0x80000008" & @CRLF)

; New buffer:
$tBuffer = DllStructCreate("dword[4]")

; Pointer to it:
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "" & _ ; 10. SET eax AND CALL
        "B8" & SwapEndian(0x80000008) & _                        ; mov eax, 0x80000008
        "0FA2" & _                                               ; cpuid
        "" & _ ; 20. ARRANGE DATA
        "A3" & SwapEndian($pBuffer) & _                          ; mov dword[$pBuffer], eax
        "891D" & SwapEndian($pBuffer + 4) & _                    ; mov dword[$pBuffer + 4], ebx
        "890D" & SwapEndian($pBuffer + 8) & _                    ; mov dword[$pBuffer + 8], ecx
        "8915" & SwapEndian($pBuffer + 12) & _                   ; mov dword[$pBuffer + 12], edx
        "" & _ ; 30. RETURN
        "C3" _
        )

; Execute it:
$iRet = _RunAtAddress($pRemoteCode)

; Return eax:
ConsoleWrite("Return: " & $iRet & @CRLF)

; Collected data:
ConsoleWrite("EAX (largest virtual and physical address sizes): " & DllStructGetData($tBuffer, 1, 1) & @CRLF)
ConsoleWrite("EBX: " & DllStructGetData($tBuffer, 1, 2) & @CRLF)
ConsoleWrite("ECX: " & DllStructGetData($tBuffer, 1, 3) & @CRLF)
ConsoleWrite("EDX: " & DllStructGetData($tBuffer, 1, 4) & @CRLF)

; Maximum number of cores
$iApicIdCoreIdSize = BitAND(DllStructGetData($tBuffer, 1, 3), 0xF) ; 0-3 ECX
ConsoleWrite("ApicIdCoreIdSize = " & $iApicIdCoreIdSize & @CRLF)
If $iApicIdCoreIdSize = 0 Then
    $IMNC = 1
Else
    $IMNC = 2 ^ $iApicIdCoreIdSize
EndIf
ConsoleWrite("Maximum number of cores " & $IMNC & @CRLF)



Func _RunAtAddress($pCode)
    Local $aCall = DllCall("user32.dll", "dword_ptr", "CallWindowProcW", "ptr", $pCode, "ptr", 0, "dword", 0, "wparam", 0, "lparam", 0)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc   ;==>_RunAtAddress

Func SwapEndian($iValue, $iSize = 0)
    If $iSize Then
        Local $sPadd = "00000000"
        Return Hex(BinaryMid($iValue, 1, $iSize)) & StringLeft($sPadd, 2 * ($iSize - BinaryLen($iValue)))
    EndIf
    Return Hex(Binary($iValue))
EndFunc   ;==>SwapEndian

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Using the WMI code creator, use the Win32_Processor drop down selection, and then look at Name. If you run the test script, you should see the name of the processor as Windows sees it. I'm not at home right now, so I don't have the actual names of the comboboxes to look at, but this should point you in the right direction. If you still need help, let us know, and once I get to my home computer I can get the exact information.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Processor info is stored inside the processor itself, on the lowest possible level. It's retrieved with CPUID instruction.

If WMI fails to get right info then the reason is something else than what you think.

I posted this somewhere already and other posted their versions too (maybe better). Again:

Thanks, that works perfectly! I didn't expect to have to use CPUID instruction directly, but without knowing an alternative to WMI with which Windows would surface this data, that'll do just fine.

Using the WMI code creator, use the Win32_Processor drop down selection, and then look at Name. If you run the test script, you should see the name of the processor as Windows sees it. I'm not at home right now, so I don't have the actual names of the comboboxes to look at, but this should point you in the right direction. If you still need help, let us know, and once I get to my home computer I can get the exact information.

As I have posted above, WMI is not showing the correct information in the Name property. It contains the string Intel Pentium III Xeon processor. The correct processor brand string is displayed in Device Manager, System Properties, and is returned using the CPUID instruction in the code posted by trancexx, but does not appear to be accessible through WMI.

What OS are you running?

XP Pro SP3 Edited by Rishodi
Link to comment
Share on other sites

  • 3 years later...
  • Moderators

ashigro, did you not notice this thread is 4 years old? Please don't resurrect old threads, as the language has evolved a lot in the last four years. If you're experiencing an issue with your script, please begin a new thread with a detailed explanation; you can even link to this thread if you believe it particularly relevent.

Edited by JLogan3o13

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...