Detecting is hyperthreading is enabled with WMI?

D

David Holcomb

Is there any way to do this with WMI? Perhaps, even, a way to query for the
number of logical versus physical CPUs? Perhaps something stored in the
registry? Or some way to query for the number of "licensed PHYSICAL
processors" (which, if different from the number of processors enumerated by
Win32_Processor would indicate a form of hyperthreading is enabled).

Thanks,
David Holcomb
 
T

Torgeir Bakken \(MVP\)

David said:
Is there any way to do this with WMI? Perhaps, even, a way to query for the
number of logical versus physical CPUs? Perhaps something stored in the
registry? Or some way to query for the number of "licensed PHYSICAL
processors" (which, if different from the number of processors enumerated by
Win32_Processor would indicate a form of hyperthreading is enabled).
Hi

You will not be able to use WMI to detect if hyperthreading is enabled
and I don't know any other script method either that will do it.


From: Steve Lee [MSFT] ([email protected])
Subject: Re: hyperthreading oddity
Newsgroups: microsoft.public.win32.programmer.wmi
Date: 2003-03-03 13:32:05 PST

<quote>
This is a known issue. WMI is currently not hyperthreading aware and
simply reports what the OS is reporting.
</quote>
 
D

David Holcomb

It is too bad that WMI does not give this info. Since I was also having
trouble with the Win32_Processor.Family returning what seemed to be
incorrect information, I looked into the possiblity of getting my own
results from the CPUID instruction from VBScript. It seems that if you
execute CPUID function 1 you can look at EBX bits 16-23 (or more
appropriately bits 23-16) if the HTT bit is set (bit 28) and the CPUID
function 0 returned GenuineIntel in the EBX/EDX/ECX registers.

I went to the Intel and AMD sites for how to execute the CPUID instruction.
Then I wrapped it in a little C program to display the CPUID functions and
all the register results like this:

C:\cpuid>cpuidx86.exe
StandardFunction:00000000,EAX:00000001,EBX:68747541,ECX:444D4163,EDX:69746E6
5
StandardFunction:00000001,EAX:00000662,EBX:00000000,ECX:00000000,EDX:0383FBF
F
ExtendedFunction:80000000,EAX:80000008,EBX:68747541,ECX:444D4163,EDX:69746E6
5
ExtendedFunction:80000001,EAX:00000762,EBX:00000000,ECX:00000000,EDX:C1C3FBF
F
ExtendedFunction:80000002,EAX:20444D41,EBX:6C687441,ECX:54286E6F,EDX:5820294
D
ExtendedFunction:80000003,EAX:39312050,EBX:002B3030,ECX:00000000,EDX:0000000
0
ExtendedFunction:80000004,EAX:00000000,EBX:00000000,ECX:00000000,EDX:0000000
0
ExtendedFunction:80000005,EAX:0408FF08,EBX:FF20FF10,ECX:40020140,EDX:4002014
0
ExtendedFunction:80000006,EAX:00000000,EBX:41004100,ECX:01008140,EDX:0000000
0
ExtendedFunction:80000007,EAX:00000000,EBX:00000000,ECX:00000000,EDX:0000000
1
ExtendedFunction:80000008,EAX:00002022,EBX:00000000,ECX:00000000,EDX:0000000
0

The program basically executes the first basic/standard CPUID function,
checks EAX and enumerates all available standard functions. Then it
executes the first extended CPUID function, checks EAX and
enumerates/executes all extended functions. This program does not attempt
to decode all the results, the idea was that some script could parse the
output and do its own decoding.

I took my simple binary and encoded it into a VBScript which can decode and
execute cpuidx86.exe, storing the output into several arrays. It is not
very pretty, perhaps I will improve on it. But I thought this might be an
interesting way to solve the problem of detecting if hyperthreading is
enabled, identify the processor with the family/model/stepping and cache
information, and possibly also leverage other useful information returned
from various CPUID functions. To decode everything, much much more would
have to be done to the script. At the moment I am only interested in
identifying if hyperthreading is enabled (and the number of physical CPUs),
and identifying the processor correctly.

Some similar CPUID programs will also calculate the processor speed. I
didn't implement that. It is another thing I might improve on later.

Unlike WMI, this script cannot enumerate this data on a remote machine using
security credentials. It has to run on the local machine (it uses WMI and
standard WSH objects). However, if the script already exists on the remote
computer, you might be able to do a Win32_Process.Create() to invoke the
script (or binary) on the remote computer. But then you still might have to
find a way to get the CPUID data back to your local computer if that is
where you want to process the results. I haven't solved all that stuff yet,
I'm taking this one step at a time. Eventually I would like to be able to
query for this data on a remote computer. I suppose there is a possibility
of creating and registering my own WMI provider that collects this data.
That would open up the possibility to query this data remotely as I would
like, but you would have to register the provider on all clients first.
That doesn't sound like a good solution to me, I would rather simply ensure
a program or script exists on a remote computer and invoke it remotely,
finding some other way to get the data back from the remote computer.

If anyone knows of a way to execute a process on a remote computer through
WMI and get its stdout (sstandard output, like from a batch file or this
cpuidx86.exe), please give me some suggestions.

I really wish WMI had the ability to return this same basic data from the
processor. I mean, I wish through the Win32_Processor class you could
simply query for the results from each CPUID function. Then, even if
Win32_Processor did not provide all the CPU properties you cared about, you
could still interpret the data for yourself. Currently WMI does provide
Win32_Processor.ProcessorId, but it only contains the EAX and EDX results
from CPUID standard function 1.

Here is my first attempt to solve this problem. It is not complete as it
probably does not work on Cyrix chips, and the CPUID part won't work on
AMD64 or IA64 machines. Still, I think this is going to work for most of my
purposes. Feel free to reply to me directly with comments, criticisms and
bugs (mailto:[email protected]).

The output will look like this (select a fixed size font to view it aligned
properly):

C:\cpuid>cscript //nologo cpuinfo.vbs
---------------------------- Processor
Information: ---------------------------
|
|
| CPU: AMD Athlon(TM) XP 1900+, 1.6 Ghz (1 proc)
|
| Architecture: x86
|
|
|
| CPUID Info:
|
| Function EAX EBX ECX EDX
|
| ======== ======== ======== ======== ========
|
| 00000000 00000001 68747541 444D4163 69746E65
|
| 00000001 00000662 00000000 00000000 0383FBFF
|
| 80000000 80000008 68747541 444D4163 69746E65
|
| 80000001 00000762 00000000 00000000 C1C3FBFF
|
| 80000002 20444D41 6C687441 54286E6F 5820294D
|
| 80000003 39312050 002B3030 00000000 00000000
|
| 80000004 00000000 00000000 00000000 00000000
|
| 80000005 0408FF08 FF20FF10 40020140 40020140
|
| 80000006 00000000 41004100 01008140 00000000
|
| 80000007 00000000 00000000 00000000 00000001
|
| 80000008 00002022 00000000 00000000 00000000
|
|
|
----------------------------------------------------------------------------
---


Copy/paste the script below into a file called cpuinfo.vbs, then run
"cscript //nologo cpuinfo.vbs".

============================== CUT HERE ==================================

szComputerName = "."
set WshShell = CreateObject("WScript.Shell")
set WMIService_CIMV2 =
GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & szComputerName &
"\root\cimv2")

call DisplayProcessorInfo()

WScript.Quit 0

'
============================================================================
' = Subroutine: DisplayProcessorInfo
' =
' = Purpose:
'
============================================================================
Public Sub DisplayProcessorInfo
dim TotalProcessors
dim ProcessorSet, Processor
dim ClockSpeed, Name, Family, Architecture
dim ArchitectureString

call PrintTitleSeparator("Processor Information:")
call PrintBlankLineWithBorder

TotalProcessors = 0
set ProcessorSet = WMIService_CIMV2.ExecQuery ("select * from
Win32_Processor")
for each Processor in ProcessorSet
TotalProcessors = TotalProcessors + 1
' CurrentClockSpeed can apparently report different results,
especially if using a laptop
' with Intel SpeedStep technology, so we use MaxClockSpeed
ClockSpeed = Processor.MaxClockSpeed
Name = LTrim(Processor.Name)
if (Right(Name, Len(" processor")) = " processor") then Name =
Left(Name, Len(Name) - Len(" processor"))
Family = Processor.Family
Architecture = Processor.Architecture
next

if (ClockSpeed >= 1000) then
call PrintFormattedLine(" CPU: " & Name & ", " &
FormatNumber(Round(ClockSpeed/1000.0, 2), 1) & " Ghz (" & TotalProcessors &
" proc)")
else
call PrintFormattedLine(" CPU: " & Name & ", " &
ClockSpeed & " Mhz (" & TotalProcessors & " proc)")
end if

ArchitectureString = ArchitectureToString(Architecture)
call PrintFormattedLine(" Architecture: " & ArchitectureString)

if (ArchitectureString = "x86") then
call QueryCPUIDx86()
end if

call PrintBlankLineWithBorder
call PrintSeparator

set ProcessorSet = Nothing

End Sub 'DisplayProcessorInfo

const MAX_CPUID_FUNCTIONS = 32

Public Sub QueryCPUIDx86
dim PathToCPUIDx86EXE
dim CPUIDFunctions_Array()
dim EAX_Array(), EBX_Array()
dim ECX_Array(), EDX_Array()

redim CPUIDFunctions_Array(MAX_CPUID_FUNCTIONS)
redim EAX_Array(MAX_CPUID_FUNCTIONS)
redim EBX_Array(MAX_CPUID_FUNCTIONS)
redim ECX_Array(MAX_CPUID_FUNCTIONS)
redim EDX_Array(MAX_CPUID_FUNCTIONS)

' Decodes CPUIDx86.EXE from this script and returns full path
CPUIDx86EXEPath = GetCPUIDx86EXEPath()

' Executes CPUIDx86.EXE and returns CPUID function result
' in arrays
call ExecuteCPUID(CPUIDx86EXEPath, _
CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

call DisplayCPUID(CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

End Sub 'QueryCPUIDx86


Public Sub ExecuteCPUID(CPUIDEXEPath, _
CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

dim lines
dim TextLine

set WshScriptExec = WshShell.Exec(CPUIDEXEPath)

lines = 0
while Not WshScriptExec.StdOut.AtEndOfStream

TextLine = WshScriptExec.StdOut.ReadLine
call ParseCPUIDOutput(TextLine, _
CPUIDFunctions_Array(lines), _
EAX_Array(lines), _
EBX_Array(lines), _
ECX_Array(lines), _
EDX_Array(lines))

lines = lines + 1

wend

lines = lines - 1

' Trim down array sizes so LBound and UBound work
redim preserve CPUIDFunctions_Array(lines)
redim preserve EAX_Array(lines)
redim preserve EBX_Array(lines)
redim preserve ECX_Array(lines)
redim preserve EDX_Array(lines)

End Sub 'ExecuteCPUID

Public Sub ParseCPUIDOutput(TextLine, _
CPUIDFunction, _
EAX, _
EBX, _
ECX, _
EDX)
dim StartPos, EndPos
dim Length

' Format is:
'
StandardFunction:00000000,EAX:00000001,EBX:68747541,ECX:444D4163,EDX:69746E6
5

StartPos = InStr(1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
CPUIDFunction = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
EAX = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
EBX = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
ECX = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
Length = Len(TextLine) - StartPos + 1
EDX = Mid(TextLine, StartPos, Length)

End Sub ' ParseCPUIDOutput

Public Sub DisplayCPUID(CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

call PrintBlankLineWithBorder
call PrintFormattedLine(" CPUID Info:")
' call PrintBlankLineWithBorder
call PrintFormattedLine(PadChar(" ", 22) & _
"Function " & _
" EAX " & _
" EBX " & _
" ECX " & _
" EDX")
call PrintFormattedLine(PadChar(" ", 22) & _
"======== " & _
"======== " & _
"======== " & _
"======== " & _
"========")
dim i
for i = LBound(CPUIDFunctions_Array) to UBound (CPUIDFunctions_Array)
call PrintFormattedLine(PadChar(" ", 22) & _
CPUIDFunctions_Array(i) & " " & _
EAX_Array(i) & " " & _
EBX_Array(i) & " " & _
ECX_Array(i) & " " & _
EDX_Array(i))
next

End Sub ' DisplayCPUID

Public Sub DecodeCPUIDx86EXE
dim ScriptName

ScriptName = WScript.ScriptFullName

End Sub 'DecodeCPUIDx86EXE

'
============================================================================
' = Function: ArchitectureToString
' =
' = Purpose: Returns textual representation of the processor Architecture
'
============================================================================
Public Function ArchitectureToString(Architecture)

select case Architecture
case 0
ArchitectureString = "x86"
case 1
ArchitectureString = "MIPS"
case 2
ArchitectureString = "Alpha"
case 3
ArchitectureString = "PowerPC"
case 6
ArchitectureString = "ia64"
case else
ArchitectureString = "Unknown" & " (" & CStr(Architecture) & ")"
end select

ArchitectureToString = ArchitectureString

End Function 'ArchitectureToString


'
============================================================================
' = Subroutine: PrintTitleSeparator
' =
' = Purpose: Centers a given title string between an equal number of hyphens
' = on either side of the string, forming a 79 character line of text.
' = Intended to be used as a title or header of a formatted block of text.
'
============================================================================
Public Sub PrintTitleSeparator(Str)
Len_Str = Len(Str)
if ((Len_Str / 2) <> (Len_Str \ 2)) then
Len_Str = Len_Str + 1
Str = Str + " "
end if
WScript.Echo PadChar("-", (79-Len_Str)/2) & " " & Str & " " &
PadChar("-", (79 - Len_Str-2)/2)
End Sub 'PrintTitleSeparator


'
============================================================================
' = Function: PrintSeparator
' =
' = Purpose: Displays 79 character line of hyphens to be used as a separator
' = line
'
============================================================================
Public Sub PrintSeparator
WScript.Echo PadChar("-", 79)
End Sub 'PrintSeparator


'
============================================================================
' = Function: PrintBlankLineWithBorder
' =
' = Purpose: Displays 79 character line of text with a vertical bar in the
' = leftmost and rightmost position. This is used to print a blank line
' = of text in combination with the other Print*Separator formatting
' = subroutines.
'
============================================================================
Public Sub PrintBlankLineWithBorder
WScript.Echo "|" & PadChar(" ", 77) & "|"
End Sub 'PrintBlankLineWithBorrder


'
============================================================================
' = Function: PrintFormattedLine
' =
' = Purpose: Similar to PrintTitleSeparator, but left-justifies text within
a
' = 79 character line of characters and places a vertical bar in the
leftmost
' = and rightmost position
'
============================================================================
Public Sub PrintFormattedLine(Str)
Str = "| " & Str
WScript.Echo Str & PadChar(" ", 78-Len(Str)) & "|"
End Sub 'PrintLine

'
============================================================================
' = Function: PadChar
' =
' = Purpose: Creates a string which consists of one particular character and
a
' = specified length. This is meant to be used to help format output which
is
' = meant to be displayed in a columnar format.
' =
' = Example:
' = WScript.Echo "JobID" & PadChar(" ", 20 - Len("JobID")) & "Status" & _
' = PadChar(" ", 15 - Len("Status")) & "Priority"
' =
' = The above would create three columns of output. The first column is 20
' = chars wide, the second is 15. The three headings are "JobID", "Status",
' = and "Priority".
'
============================================================================
Function PadChar(char, length)
dim str
dim i

str = ""
for i = 1 to length
str = str + char
next

PadChar = str
End Function


const ForWriting = 2
const TristateUseDefault = 1
const TristateTrue = -1
const TristateFalse = 0

Function GetCPUIDx86EXEPath()
dim StringCPUIDx86EXE

StringCPUIDx86EXE = _
"4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000
00000" & _
"0000000000000000000000000000000000000000D80000000E1FBA0E00B409CD21B8014CCD2
15468" & _
"69732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0
D0D0A" & _
"2400000000000000364A251D722B4B4E722B4B4E722B4B4EF123444E702B4B4E722B4A4E662
B4B4E" & _
"F123164E712B4B4EFC23144E7C2B4B4EF123114E732B4B4E52696368722B4B4E00000000000
00000" & _
"00000000000000000000000000000000504500004C010200595317410000000000000000E00
00F01" & _
"0B01070A0008000000020000000000000314000000100000002000000000000100100000000
20000" & _
"050002000500020004000000000000000030000000040000631800000300008000000400002
00000" & _
"0000100000100000000000001000000000000000000000000C1600002800000000000000000
00000" & _
"000000000000000000000000000000000000000000000000601000001C00000000000000000
00000" & _
"0000000000000000000000000000000018110000400000000000000000000000001000004C0
00000" & _
"0000000000000000000000000000000000000000000000002E7465787400000078070000001
00000" & _
"0008000000040000000000000000000000000000200000602E6461746100000024000000002
00000" & _
"00020000000C0000000000000000000000000000400000C0000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000801600008A160000941600009C1
60000" & _
"B0160000BA160000C2160000D0160000DA160000E2160000EE160000FE1600000A1700001E1
70000" & _
"2E1700003E1700004C1700006A1700000000000000000000000000000000000000000000000
00000" & _
"000000005953174100000000020000004F000000601100006005000046756E6374696F6E3A2
53038" & _
"6C582C4541583A2530386C582C4542583A2530386C582C4543583A2530386C582C4544583A2
53038" & _
"6C580A00457874656E646564000000005374616E64617264000000004552524F523A2043505
54944" & _
"20696E737472756374696F6E206E6F7420737570706F727465640A0000000000FFFFFFFFB01
20001" & _
"B612000100000000FFFFFFFF4F1500016315000100000000480000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"0000000004200001B0110001010000004E423130000000005953174101000000433A5C64626
72E36" & _
"2E332E31315C73646B5C73616D706C65735C63707569645C6F626A63686B5F776E65745F783
8365C" & _
"693338365C63707569642E706462000090150000000000000000000000000000558BEC83EC1
0C745" & _
"F000000000C745F800000000C745F400000000C745FC000000008B45080FA28945F0895DF88
94DF4" & _
"8955FC8B450C8B4DF089088B55108B45F889028B4D148B55F489118B45188B4DFC89088BE55
DC214" & _
"00CCCCCCCCCCCCCC558BEC817D0800000080731068C0100001FF150010000183C404EB0E68B
41000" & _
"01FF150010000183C4048B4518508B4D14518B5510528B450C508B4D0851687C100001FF150
01000" & _
"0183C4185DC21400558BEC6AFF68F8100001689015000164A10000000050648925000000008
3C4DC" & _
"5356578965E8C745FC0000000033C033DB33C933D20FA2C745FCFFFFFFFFEB36B801000000C
38B65" & _
"E868CC100001A10810000183C04050FF150410000183C408C745CCFFFFFFFFC745FCFFFFFFF
F8B45" & _
"CCE90C0100008D4DE4518D55D4528D45D8508D4DD0516A00E8C3FEFFFF8B55D08955DC8B45E
4508B" & _
"4DD4518B55D8528B45D0506A00E806FFFFFFC745E001000000EB098B4DE083C101894DE08B5
5E03B" & _
"55DC77348D45E4508D4DD4518D55D8528D45D0508B4DE051E873FEFFFF8B55E4528B45D4508
B4DD8" & _
"518B55D0528B45E050E8BAFEFFFFEBBB8D4DE4518D55D4528D45D8508D4DD0516800000080E
83EFE" & _
"FFFF8B55D08955DC8B45E4508B4DD4518B55D8528B45D0506800000080E87EFEFFFFC745E00
10000" & _
"80EB098B4DE083C101894DE08B55E03B55DC77348D45E4508D4DD4518D55D8528D45D0508B4
DE051" & _
"E8EBFDFFFF8B55E4528B45D4508B4DD8518B55D0528B45E050E832FEFFFFEBBB33C08B4DF06
4890D" & _
"000000005F5E5B8BE55DC36A286808110001E8A901000066813D000000014D5A7528A13C000
00181" & _
"B8000000015045000075170FB7881800000181F90B010000742181F90B02000074068365E40
0EB2A" & _
"83B8840000010E76F133C93988F8000001EB1183B8740000010E76DE33C93988E80000010F9
5C189" & _
"4DE48365FC006A01FF154010000159830D18200001FF830D1C200001FFFF153C1000018B0D1
42000" & _
"018908FF15381000018B0D102000018908A1341000018B00A320200001E8FA000000833D002
00001" & _
"00750C68B4150001FF153010000159E8CE00000068581000016854100001E8B9000000A10C2
00001" & _
"8945DC8D45DC50FF35082000018D45E0508D45D8508D45D450FF15281000018945CC6850100
00168" & _
"4C100001E8830000008B45E08B0D241000018901FF75E0FF75D8FF75D4E83EFDFFFF83C4308
BF089" & _
"75C8837DE400750756FF1520100001FF151C100001EB2D8B45EC8B088B09894DD05051E8360
00000" & _
"5959C38B65E88B75D0837DE400750756FF1514100001FF1510100001834DFCFF8BC6E86C000
000C3" & _
"CCCCCCCCCCCCCCCCFF250C100001FF2518100001FF252C10000168000003006800000100E85
30000" & _
"005959C333C0C3CC689015000164A100000000508B442410896C24108D6C24102BE05356578
B45F8" & _
"8965E8508B45FCC745FCFFFFFFFF8945F88D45F064A300000000C38B4DF064890D000000005
95F5E" & _
"5BC951C3FF2544100001CCCC3416000000000000000000005E1700000010000000000000000
00000" & _
"000000000000000000000000801600008A160000941600009C160000B0160000BA160000C21
60000" & _
"D0160000DA160000E2160000EE160000FE1600000A1700001E1700002E1700003E1700004C1
70000" & _
"6A17000000000000EF027072696E74660000A902667072696E74660044015F696F620000F20
05F65" & _
"78636570745F68616E646C6572330000CA005F635F6578697400FB005F65786974004E005F5
86370" & _
"7446696C74657200CD005F636578697400009A0265786974000071005F5F696E6974656E760
07000" & _
"5F5F6765746D61696E617267730040015F696E69747465726D009E005F5F736574757365726
D6174" & _
"686572720000BB005F61646A7573745F66646976000083005F5F705F5F636F6D6D6F6465000
08800" & _
"5F5F705F5F666D6F646500009C005F5F7365745F6170705F7479706500006D73766372742E6
46C6C" & _
"0000DB005F636F6E74726F6C667000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"0000000000000000000000000000000000000000000000000000000000000000010000004EE
640BB" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000000000000000000000000000000
00000" & _
"000000000000000000000000000000000000000000000000"
dim BinFile
set fso = CreateObject("Scripting.FileSystemObject")
set f = fso.CreateTextFile("cpuidx86.exe")

filelen = Len(StringCPUIDx86EXE)

for i = 1 to filelen step 2
while ((i <= filelen) And (IsWhiteSpace(Mid(StringCPUIDx86EXE, i,
1))))
i = i + 1
wend

if (i <= filelen) then
BinFile = BinFile & Chr(HexStringToInt(Mid(StringCPUIDx86EXE, i,
2)))
end if
next

call f.Write(BinFile)
call f.Close()

GetCPUIDx86EXEPath = fso.GetAbsolutePathName("cpuidx86.exe")

set f = Nothing
set fso = Nothing

End Function 'GetCPUIDx86EXEPath

Public Function IsWhiteSpace(char)
dim result
if (Len(char) = 0) then
result = false
elseif (Asc(char) < 32) then
result = True
else
result = False
end if
IsWhiteSpace = result
End Function

Public Function HexStringToInt(hexstring)
dim i, dblval, hexchar, hexval
' Hex is treated as unsigned for the conversion, so
' use CDbl
dblval = CDbl(0)
for i = 1 to Len(hexstring)
hexchar = Mid(hexstring, i, 1)
if (IsNumeric(hexchar)) then
hexval = CLng(Mid(hexstring, i, 1))
else
hexval = 10 + CLng(Asc(UCase(Mid(hexstring, i, 1))) - Asc("A"))
end if
dblval = CDbl(dblval*16) + CDbl(hexval)
next
HexStringToInt = dblval
End Function
============================== END CUT ==================================

Torgeir Bakken (MVP) said:
David said:
Is there any way to do this with WMI? Perhaps, even, a way to query for the
number of logical versus physical CPUs? Perhaps something stored in the
registry? Or some way to query for the number of "licensed PHYSICAL
processors" (which, if different from the number of processors enumerated by
Win32_Processor would indicate a form of hyperthreading is enabled).
Hi

You will not be able to use WMI to detect if hyperthreading is enabled
and I don't know any other script method either that will do it.


From: Steve Lee [MSFT] ([email protected])
Subject: Re: hyperthreading oddity
Newsgroups: microsoft.public.win32.programmer.wmi
Date: 2003-03-03 13:32:05 PST

<quote>
This is a known issue. WMI is currently not hyperthreading aware and
simply reports what the OS is reporting.
</quote>


--
torgeir, Microsoft MVP Scripting and WMI, Porsgrunn Norway
Administration scripting examples and an ONLINE version of
the 1328 page Scripting Guide:
http://www.microsoft.com/technet/scriptcenter/default.mspx
 
D

David Holcomb

[Sorry for re-post, the last time I replied Outlook Express was configured to ]
[truncate or wrap my lines at 76 characters.]
[Plus, posting in HTML format wreaks havoc on your ability to copy/paste the]
[text directly into a text file. So I am re-posting as plain text.]
[Hope this works...]

It is too bad that WMI does not give this info. Since I was also having
trouble with the Win32_Processor.Family returning what seemed to be
incorrect information, I looked into the possiblity of getting my own
results from the CPUID instruction from VBScript. It seems that if you
execute CPUID function 1 you can look at EBX bits 16-23 (or more
appropriately bits 23-16) if the HTT bit is set (bit 28) and the CPUID
function 0 returned GenuineIntel in the EBX/EDX/ECX registers.

I went to the Intel and AMD sites for how to execute the CPUID instruction.
Then I wrapped it in a little C program to display the CPUID functions and
all the register results like this:

C:\cpuid>cpuidx86.exe
StandardFunction:00000000,EAX:00000001,EBX:68747541,ECX:444D4163,EDX:69746E65
StandardFunction:00000001,EAX:00000662,EBX:00000000,ECX:00000000,EDX:0383FBFF
ExtendedFunction:80000000,EAX:80000008,EBX:68747541,ECX:444D4163,EDX:69746E65
ExtendedFunction:80000001,EAX:00000762,EBX:00000000,ECX:00000000,EDX:C1C3FBFF
ExtendedFunction:80000002,EAX:20444D41,EBX:6C687441,ECX:54286E6F,EDX:5820294D
ExtendedFunction:80000003,EAX:39312050,EBX:002B3030,ECX:00000000,EDX:00000000
ExtendedFunction:80000004,EAX:00000000,EBX:00000000,ECX:00000000,EDX:00000000
ExtendedFunction:80000005,EAX:0408FF08,EBX:FF20FF10,ECX:40020140,EDX:40020140
ExtendedFunction:80000006,EAX:00000000,EBX:41004100,ECX:01008140,EDX:00000000
ExtendedFunction:80000007,EAX:00000000,EBX:00000000,ECX:00000000,EDX:00000001
ExtendedFunction:80000008,EAX:00002022,EBX:00000000,ECX:00000000,EDX:00000000

The program basically executes the first basic/standard CPUID function,
checks EAX and enumerates all available standard functions. Then it
executes the first extended CPUID function, checks EAX and
enumerates/executes all extended functions. This program does not attempt
to decode all the results, the idea was that some script could parse the
output and do its own decoding.

I took my simple binary and encoded it into a VBScript which can decode and
execute cpuidx86.exe, storing the output into several arrays. It is not
very pretty, perhaps I will improve on it. But I thought this might be an
interesting way to solve the problem of detecting if hyperthreading is
enabled, identify the processor with the family/model/stepping and cache
information, and possibly also leverage other useful information returned
from various CPUID functions. To decode everything, much much more would
have to be done to the script. At the moment I am only interested in
identifying if hyperthreading is enabled (and the number of physical CPUs),
and identifying the processor correctly.

Some similar CPUID programs will also calculate the processor speed. I
didn't implement that. It is another thing I might improve on later.

Unlike WMI, this script cannot enumerate this data on a remote machine using
security credentials. It has to run on the local machine (it uses WMI and
standard WSH objects). However, if the script already exists on the remote
computer, you might be able to do a Win32_Process.Create() to invoke the
script (or binary) on the remote computer. But then you still might have to
find a way to get the CPUID data back to your local computer if that is
where you want to process the results. I haven't solved all that stuff yet,
I'm taking this one step at a time. Eventually I would like to be able to
query for this data on a remote computer. I suppose there is a possibility
of creating and registering my own WMI provider that collects this data.
That would open up the possibility to query this data remotely as I would
like, but you would have to register the provider on all clients first.
That doesn't sound like a good solution to me, I would rather simply ensure
a program or script exists on a remote computer and invoke it remotely,
finding some other way to get the data back from the remote computer.

If anyone knows of a way to execute a process on a remote computer through
WMI and get its stdout (sstandard output, like from a batch file or this
cpuidx86.exe), please give me some suggestions.

I really wish WMI had the ability to return this same basic data from the
processor. I mean, I wish through the Win32_Processor class you could
simply query for the results from each CPUID function. Then, even if
Win32_Processor did not provide all the CPU properties you cared about, you
could still interpret the data for yourself. Currently WMI does provide
Win32_Processor.ProcessorId, but it only contains the EAX and EDX results
from CPUID standard function 1.

Here is my first attempt to solve this problem. It is not complete as it
probably does not work on Cyrix chips, and the CPUID part won't work on
AMD64 or IA64 machines. Still, I think this is going to work for most of my
purposes. Feel free to reply to me directly with comments, criticisms and
bugs (mailto:[email protected]).

The output will look like this (select a fixed size font to view it aligned
properly):

C:\cpuid>cscript //nologo cpuinfo.vbs
---------------------------- Processor Information: ---------------------------
| |
| CPU: AMD Athlon(TM) XP 1900+, 1.6 Ghz (1 proc) |
| Architecture: x86 |
| |
| CPUID Info: |
| Function EAX EBX ECX EDX |
| ======== ======== ======== ======== ======== |
| 00000000 00000001 68747541 444D4163 69746E65 |
| 00000001 00000662 00000000 00000000 0383FBFF |
| 80000000 80000008 68747541 444D4163 69746E65 |
| 80000001 00000762 00000000 00000000 C1C3FBFF |
| 80000002 20444D41 6C687441 54286E6F 5820294D |
| 80000003 39312050 002B3030 00000000 00000000 |
| 80000004 00000000 00000000 00000000 00000000 |
| 80000005 0408FF08 FF20FF10 40020140 40020140 |
| 80000006 00000000 41004100 01008140 00000000 |
| 80000007 00000000 00000000 00000000 00000001 |
| 80000008 00002022 00000000 00000000 00000000 |
| |
-------------------------------------------------------------------------------

This output is from a Pentium 4 Xeon processor with Hyperthreading , or Hyper-
threading, enabled:

C:\cpuinfo>cscript cpuinfo.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

---------------------------- Processor Information: ---------------------------
| |
| CPU: Intel(R) Pentium(R) 4 CPU 2.40GHz, 2.4 Ghz (2 proc) |
| Architecture: x86 |
| |
| CPUID Info: |
| Function EAX EBX ECX EDX |
| ======== ======== ======== ======== ======== |
| 00000000 00000002 756E6547 6C65746E 49656E69 |
| 00000001 00000F29 00020809 00004400 BFEBFBFF |
| 00000002 665B5001 00000000 00000000 007B7040 |
| 80000000 80000004 00000000 00000000 00000000 |
| 80000001 00000000 00000000 00000000 00000000 |
| 80000002 20202020 20202020 20202020 6E492020 |
| 80000003 286C6574 50202952 69746E65 52286D75 |
| 80000004 20342029 20555043 30342E32 007A4847 |
| |
-------------------------------------------------------------------------------

Copy/paste the script below into a file called cpuinfo.vbs, then run
"cscript //nologo cpuinfo.vbs".

=========================== CUT HERE ===========================
szComputerName = "."
set WshShell = CreateObject("WScript.Shell")
set WMIService_CIMV2 = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & szComputerName & "\root\cimv2")

call DisplayProcessorInfo()

WScript.Quit 0

' ============================================================================
' = Subroutine: DisplayProcessorInfo
' =
' = Purpose:
' ============================================================================
Public Sub DisplayProcessorInfo
dim TotalProcessors
dim ProcessorSet, Processor
dim ClockSpeed, Name, Family, Architecture
dim ArchitectureString

call PrintTitleSeparator("Processor Information:")
call PrintBlankLineWithBorder

TotalProcessors = 0
set ProcessorSet = WMIService_CIMV2.ExecQuery ("select * from Win32_Processor")
for each Processor in ProcessorSet
TotalProcessors = TotalProcessors + 1
' CurrentClockSpeed can apparently report different results,
' especially if using a laptop with Intel SpeedStep technology,
' so we use MaxClockSpeed
ClockSpeed = Processor.MaxClockSpeed
Name = LTrim(Processor.Name)
if (Right(Name, Len(" processor")) = " processor") then
Name = Left(Name, Len(Name) - Len(" processor"))
end if
Family = Processor.Family
Architecture = Processor.Architecture
next

if (ClockSpeed >= 1000) then
call PrintFormattedLine(" CPU: " & Name & ", " & _
FormatNumber(Round(ClockSpeed/1000.0, 2), 1) & _
" Ghz (" & TotalProcessors & " proc)")
else
call PrintFormattedLine(" CPU: " & Name & ", " & _
ClockSpeed & _
" Mhz (" & TotalProcessors & " proc)")
end if

ArchitectureString = ArchitectureToString(Architecture)
call PrintFormattedLine(" Architecture: " & ArchitectureString)

if (ArchitectureString = "x86") then
call QueryCPUIDx86()
end if

call PrintBlankLineWithBorder
call PrintSeparator

set ProcessorSet = Nothing

End Sub 'DisplayProcessorInfo

const MAX_CPUID_FUNCTIONS = 32

Public Sub QueryCPUIDx86
dim PathToCPUIDx86EXE
dim CPUIDFunctions_Array()
dim EAX_Array(), EBX_Array()
dim ECX_Array(), EDX_Array()

redim CPUIDFunctions_Array(MAX_CPUID_FUNCTIONS)
redim EAX_Array(MAX_CPUID_FUNCTIONS)
redim EBX_Array(MAX_CPUID_FUNCTIONS)
redim ECX_Array(MAX_CPUID_FUNCTIONS)
redim EDX_Array(MAX_CPUID_FUNCTIONS)

' Decodes CPUIDx86.EXE from this script and returns full path
CPUIDx86EXEPath = GetCPUIDx86EXEPath()

' Executes CPUIDx86.EXE and returns CPUID function result
' in arrays
call ExecuteCPUID(CPUIDx86EXEPath, _
CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

call DisplayCPUID(CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

End Sub 'QueryCPUIDx86


Public Sub ExecuteCPUID(CPUIDEXEPath, _
CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

dim lines
dim TextLine

set WshScriptExec = WshShell.Exec(CPUIDEXEPath)

lines = 0
while Not WshScriptExec.StdOut.AtEndOfStream

TextLine = WshScriptExec.StdOut.ReadLine
call ParseCPUIDOutput(TextLine, _
CPUIDFunctions_Array(lines), _
EAX_Array(lines), _
EBX_Array(lines), _
ECX_Array(lines), _
EDX_Array(lines))

lines = lines + 1

wend

lines = lines - 1

' Trim down array sizes so LBound and UBound work
redim preserve CPUIDFunctions_Array(lines)
redim preserve EAX_Array(lines)
redim preserve EBX_Array(lines)
redim preserve ECX_Array(lines)
redim preserve EDX_Array(lines)

End Sub 'ExecuteCPUID

Public Sub ParseCPUIDOutput(TextLine, _
CPUIDFunction, _
EAX, _
EBX, _
ECX, _
EDX)
dim StartPos, EndPos
dim Length

' Format is:
' StandardFunction:00000000,EAX:00000001,EBX:68747541,ECX:444D4163,EDX:69746E65

StartPos = InStr(1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
CPUIDFunction = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
EAX = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
EBX = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
EndPos = Instr(StartPos, TextLine, ",", vbBinaryCompare)
Length = EndPos - StartPos
ECX = Mid(TextLine, StartPos, Length)

StartPos = InStr(EndPos + 1, TextLine, ":", vbBinaryCompare) + 1
Length = Len(TextLine) - StartPos + 1
EDX = Mid(TextLine, StartPos, Length)

End Sub ' ParseCPUIDOutput

Public Sub DisplayCPUID(CPUIDFunctions_Array, _
EAX_Array, _
EBX_Array, _
ECX_Array, _
EDX_Array)

call PrintBlankLineWithBorder
call PrintFormattedLine(" CPUID Info:")

call PrintFormattedLine(PadChar(" ", 22) & _
"Function " & _
" EAX " & _
" EBX " & _
" ECX " & _
" EDX")
call PrintFormattedLine(PadChar(" ", 22) & _
"======== " & _
"======== " & _
"======== " & _
"======== " & _
"========")
dim i
for i = LBound(CPUIDFunctions_Array) to UBound (CPUIDFunctions_Array)
call PrintFormattedLine(PadChar(" ", 22) & _
CPUIDFunctions_Array(i) & " " & _
EAX_Array(i) & " " & _
EBX_Array(i) & " " & _
ECX_Array(i) & " " & _
EDX_Array(i))
next

End Sub ' DisplayCPUID

Public Sub DecodeCPUIDx86EXE
dim ScriptName

ScriptName = WScript.ScriptFullName

End Sub 'DecodeCPUIDx86EXE

' ============================================================================
' = Function: ArchitectureToString
' =
' = Purpose: Returns textual representation of the processor Architecture
' ============================================================================
Public Function ArchitectureToString(Architecture)

select case Architecture
case 0
ArchitectureString = "x86"
case 1
ArchitectureString = "MIPS"
case 2
ArchitectureString = "Alpha"
case 3
ArchitectureString = "PowerPC"
case 6
ArchitectureString = "ia64"
case else
ArchitectureString = "Unknown" & " (" & CStr(Architecture) & ")"
end select

ArchitectureToString = ArchitectureString

End Function 'ArchitectureToString


' ============================================================================
' = Subroutine: PrintTitleSeparator
' =
' = Purpose: Centers a given title string between an equal number of hyphens
' = on either side of the string, forming a 79 character line of text.
' = Intended to be used as a title or header of a formatted block of text.
' ============================================================================
Public Sub PrintTitleSeparator(Str)
Len_Str = Len(Str)
if ((Len_Str / 2) <> (Len_Str \ 2)) then
Len_Str = Len_Str + 1
Str = Str + " "
end if
WScript.Echo PadChar("-", (79-Len_Str)/2) & " " & Str & " " & _
PadChar("-", (79 - Len_Str-2)/2)
End Sub 'PrintTitleSeparator


' ============================================================================
' = Function: PrintSeparator
' =
' = Purpose: Displays 79 character line of hyphens to be used as a separator
' = line
' ============================================================================
Public Sub PrintSeparator
WScript.Echo PadChar("-", 79)
End Sub 'PrintSeparator


' ============================================================================
' = Function: PrintBlankLineWithBorder
' =
' = Purpose: Displays 79 character line of text with a vertical bar in the
' = leftmost and rightmost position. This is used to print a blank line
' = of text in combination with the other Print*Separator formatting
' = subroutines.
' ============================================================================
Public Sub PrintBlankLineWithBorder
WScript.Echo "|" & PadChar(" ", 77) & "|"
End Sub 'PrintBlankLineWithBorrder


' ============================================================================
' = Function: PrintFormattedLine
' =
' = Purpose: Similar to PrintTitleSeparator, but left-justifies text within a
' = 79 character line of characters and places a vertical bar in the leftmost
' = and rightmost position
' ============================================================================
Public Sub PrintFormattedLine(Str)
Str = "| " & Str
WScript.Echo Str & PadChar(" ", 78-Len(Str)) & "|"
End Sub 'PrintLine

' ============================================================================
' = Function: PadChar
' =
' = Purpose: Creates a string which consists of one particular character and a
' = specified length. This is meant to be used to help format output which is
' = meant to be displayed in a columnar format.
' =
' = Example:
' = WScript.Echo "JobID" & PadChar(" ", 20 - Len("JobID")) & "Status" & _
' = PadChar(" ", 15 - Len("Status")) & "Priority"
' =
' = The above would create three columns of output. The first column is 20
' = chars wide, the second is 15. The three headings are "JobID", "Status",
' = and "Priority".
' ============================================================================
Function PadChar(char, length)
dim str
dim i

str = ""
for i = 1 to length
str = str + char
next

PadChar = str
End Function


const ForWriting = 2
const TristateUseDefault = 1
const TristateTrue = -1
const TristateFalse = 0

Function GetCPUIDx86EXEPath()
dim StringCPUIDx86EXE

StringCPUIDx86EXE = _
"4D5A90000300000004000000FFFF0000B80000000000000040000000000000000000000000000000" & _
"0000000000000000000000000000000000000000D80000000E1FBA0E00B409CD21B8014CCD215468" & _
"69732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A" & _
"2400000000000000364A251D722B4B4E722B4B4E722B4B4EF123444E702B4B4E722B4A4E662B4B4E" & _
"F123164E712B4B4EFC23144E7C2B4B4EF123114E732B4B4E52696368722B4B4E0000000000000000" & _
"00000000000000000000000000000000504500004C010200595317410000000000000000E0000F01" & _
"0B01070A000800000002000000000000031400000010000000200000000000010010000000020000" & _
"05000200050002000400000000000000003000000004000063180000030000800000040000200000" & _
"0000100000100000000000001000000000000000000000000C160000280000000000000000000000" & _
"000000000000000000000000000000000000000000000000601000001C0000000000000000000000" & _
"0000000000000000000000000000000018110000400000000000000000000000001000004C000000" & _
"0000000000000000000000000000000000000000000000002E746578740000007807000000100000" & _
"0008000000040000000000000000000000000000200000602E646174610000002400000000200000" & _
"00020000000C0000000000000000000000000000400000C000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"000000000000000000000000000000000000000000000000801600008A160000941600009C160000" & _
"B0160000BA160000C2160000D0160000DA160000E2160000EE160000FE1600000A1700001E170000" & _
"2E1700003E1700004C1700006A170000000000000000000000000000000000000000000000000000" & _
"000000005953174100000000020000004F000000601100006005000046756E6374696F6E3A253038" & _
"6C582C4541583A2530386C582C4542583A2530386C582C4543583A2530386C582C4544583A253038" & _
"6C580A00457874656E646564000000005374616E64617264000000004552524F523A204350554944" & _
"20696E737472756374696F6E206E6F7420737570706F727465640A0000000000FFFFFFFFB0120001" & _
"B612000100000000FFFFFFFF4F150001631500010000000048000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"0000000004200001B0110001010000004E423130000000005953174101000000433A5C6462672E36" & _
"2E332E31315C73646B5C73616D706C65735C63707569645C6F626A63686B5F776E65745F7838365C" & _
"693338365C63707569642E706462000090150000000000000000000000000000558BEC83EC10C745" & _
"F000000000C745F800000000C745F400000000C745FC000000008B45080FA28945F0895DF8894DF4" & _
"8955FC8B450C8B4DF089088B55108B45F889028B4D148B55F489118B45188B4DFC89088BE55DC214" & _
"00CCCCCCCCCCCCCC558BEC817D0800000080731068C0100001FF150010000183C404EB0E68B41000" & _
"01FF150010000183C4048B4518508B4D14518B5510528B450C508B4D0851687C100001FF15001000" & _
"0183C4185DC21400558BEC6AFF68F8100001689015000164A100000000506489250000000083C4DC" & _
"5356578965E8C745FC0000000033C033DB33C933D20FA2C745FCFFFFFFFFEB36B801000000C38B65" & _
"E868CC100001A10810000183C04050FF150410000183C408C745CCFFFFFFFFC745FCFFFFFFFF8B45" & _
"CCE90C0100008D4DE4518D55D4528D45D8508D4DD0516A00E8C3FEFFFF8B55D08955DC8B45E4508B" & _
"4DD4518B55D8528B45D0506A00E806FFFFFFC745E001000000EB098B4DE083C101894DE08B55E03B" & _
"55DC77348D45E4508D4DD4518D55D8528D45D0508B4DE051E873FEFFFF8B55E4528B45D4508B4DD8" & _
"518B55D0528B45E050E8BAFEFFFFEBBB8D4DE4518D55D4528D45D8508D4DD0516800000080E83EFE" & _
"FFFF8B55D08955DC8B45E4508B4DD4518B55D8528B45D0506800000080E87EFEFFFFC745E0010000" & _
"80EB098B4DE083C101894DE08B55E03B55DC77348D45E4508D4DD4518D55D8528D45D0508B4DE051" & _
"E8EBFDFFFF8B55E4528B45D4508B4DD8518B55D0528B45E050E832FEFFFFEBBB33C08B4DF064890D" & _
"000000005F5E5B8BE55DC36A286808110001E8A901000066813D000000014D5A7528A13C00000181" & _
"B8000000015045000075170FB7881800000181F90B010000742181F90B02000074068365E400EB2A" & _
"83B8840000010E76F133C93988F8000001EB1183B8740000010E76DE33C93988E80000010F95C189" & _
"4DE48365FC006A01FF154010000159830D18200001FF830D1C200001FFFF153C1000018B0D142000" & _
"018908FF15381000018B0D102000018908A1341000018B00A320200001E8FA000000833D00200001" & _
"00750C68B4150001FF153010000159E8CE00000068581000016854100001E8B9000000A10C200001" & _
"8945DC8D45DC50FF35082000018D45E0508D45D8508D45D450FF15281000018945CC685010000168" & _
"4C100001E8830000008B45E08B0D241000018901FF75E0FF75D8FF75D4E83EFDFFFF83C4308BF089" & _
"75C8837DE400750756FF1520100001FF151C100001EB2D8B45EC8B088B09894DD05051E836000000" & _
"5959C38B65E88B75D0837DE400750756FF1514100001FF1510100001834DFCFF8BC6E86C000000C3" & _
"CCCCCCCCCCCCCCCCFF250C100001FF2518100001FF252C10000168000003006800000100E8530000" & _
"005959C333C0C3CC689015000164A100000000508B442410896C24108D6C24102BE05356578B45F8" & _
"8965E8508B45FCC745FCFFFFFFFF8945F88D45F064A300000000C38B4DF064890D00000000595F5E" & _
"5BC951C3FF2544100001CCCC3416000000000000000000005E170000001000000000000000000000" & _
"000000000000000000000000801600008A160000941600009C160000B0160000BA160000C2160000" & _
"D0160000DA160000E2160000EE160000FE1600000A1700001E1700002E1700003E1700004C170000" & _
"6A17000000000000EF027072696E74660000A902667072696E74660044015F696F620000F2005F65" & _
"78636570745F68616E646C6572330000CA005F635F6578697400FB005F65786974004E005F586370" & _
"7446696C74657200CD005F636578697400009A0265786974000071005F5F696E6974656E76007000" & _
"5F5F6765746D61696E617267730040015F696E69747465726D009E005F5F736574757365726D6174" & _
"686572720000BB005F61646A7573745F66646976000083005F5F705F5F636F6D6D6F646500008800" & _
"5F5F705F5F666D6F646500009C005F5F7365745F6170705F7479706500006D73766372742E646C6C" & _
"0000DB005F636F6E74726F6C66700000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"0000000000000000000000000000000000000000000000000000000000000000010000004EE640BB" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"00000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
"000000000000000000000000000000000000000000000000"
dim BinFile
set fso = CreateObject("Scripting.FileSystemObject")
set f = fso.CreateTextFile("cpuidx86.exe")

filelen = Len(StringCPUIDx86EXE)

for i = 1 to filelen step 2
while ((i <= filelen) And (IsWhiteSpace(Mid(StringCPUIDx86EXE, i, 1))))
i = i + 1
wend

if (i <= filelen) then
BinFile = BinFile & Chr(HexStringToInt(Mid(StringCPUIDx86EXE, i, 2)))
end if
next

call f.Write(BinFile)
call f.Close()

GetCPUIDx86EXEPath = fso.GetAbsolutePathName("cpuidx86.exe")

set f = Nothing
set fso = Nothing

End Function 'GetCPUIDx86EXEPath

Public Function IsWhiteSpace(char)
dim result
if (Len(char) = 0) then
result = false
elseif (Asc(char) < 32) then
result = True
else
result = False
end if
IsWhiteSpace = result
End Function

Public Function HexStringToInt(hexstring)
dim i, dblval, hexchar, hexval
' Hex is treated as unsigned for the conversion, so
' use CDbl
dblval = CDbl(0)
for i = 1 to Len(hexstring)
hexchar = Mid(hexstring, i, 1)
if (IsNumeric(hexchar)) then
hexval = CLng(Mid(hexstring, i, 1))
else
hexval = 10 + CLng(Asc(UCase(Mid(hexstring, i, 1))) - Asc("A"))
end if
dblval = CDbl(dblval*16) + CDbl(hexval)
next
HexStringToInt = dblval
End Function
=========================== END CUT ===========================

Torgeir Bakken (MVP) said:
David said:
Is there any way to do this with WMI? Perhaps, even, a way to query for the
number of logical versus physical CPUs? Perhaps something stored in the
registry? Or some way to query for the number of "licensed PHYSICAL
processors" (which, if different from the number of processors enumerated by
Win32_Processor would indicate a form of hyperthreading is enabled).
Hi

You will not be able to use WMI to detect if hyperthreading is enabled
and I don't know any other script method either that will do it.


From: Steve Lee [MSFT] ([email protected])
Subject: Re: hyperthreading oddity
Newsgroups: microsoft.public.win32.programmer.wmi
Date: 2003-03-03 13:32:05 PST

<quote>
This is a known issue. WMI is currently not hyperthreading aware and
simply reports what the OS is reporting.
</quote>


--
torgeir, Microsoft MVP Scripting and WMI, Porsgrunn Norway
Administration scripting examples and an ONLINE version of
the 1328 page Scripting Guide:
http://www.microsoft.com/technet/scriptcenter/default.mspx

Torgeir Bakken (MVP) said:
David said:
Is there any way to do this with WMI? Perhaps, even, a way to query for the number of logical versus physical CPUs? Perhaps
something stored in the registry? Or some way to query for the number of "licensed PHYSICAL processors" (which, if different
from the number of processors enumerated by Win32_Processor would indicate a form of hyperthreading is enabled).
Hi

You will not be able to use WMI to detect if hyperthreading is enabled
and I don't know any other script method either that will do it.


From: Steve Lee [MSFT] ([email protected])
Subject: Re: hyperthreading oddity
Newsgroups: microsoft.public.win32.programmer.wmi
Date: 2003-03-03 13:32:05 PST

<quote>
This is a known issue. WMI is currently not hyperthreading aware and
simply reports what the OS is reporting.
</quote>


--
torgeir, Microsoft MVP Scripting and WMI, Porsgrunn Norway
Administration scripting examples and an ONLINE version of
the 1328 page Scripting Guide:
http://www.microsoft.com/technet/scriptcenter/default.mspx
 
S

Stuart Coney

Hi David,

I have a similar issue right now.....

I looked around after reading and trying your vbscript with embedded .exe
and found a code example on the Intel Developers site aimed at software
vendors who wanted to license their software on a processor or logical
processor basis.....

anyway, it's called cpucount and is downloadable in both .exe and .cpp
source. Unfortunately it requires the user to press ENTER at the end of
the cmd line run (it uses a getchar();)....I will re compile it minus this
statement and use psexec from sysinternals.com to round robin the production
servers here.

Anyway the Intel download location is

http://www.intel.com/cd/ids/develop...essors/ia32/pentium4/hyperthreading/19122.htm

Hope this is of use to you, good luck
Stuart Coney
 
Joined
Sep 9, 2005
Messages
1
Reaction score
0
code error

When I run the VBS code above I get an error:
c:\test.vbs(434, 1) Microsoft VBScript runtime error: Invalid procedure call or argument: 'Chr'

This is the line of code on line 434.
BinFile = BinFile & Chr(HexStringToInt(Mid(StringCPUIDx86EXE, i, 2)))

I'm running WinXP SP2.
 
Joined
Jun 20, 2007
Messages
1
Reaction score
0
Zico said:
When I run the VBS code above I get an error:
c:\test.vbs(434, 1) Microsoft VBScript runtime error: Invalid procedure call or argument: 'Chr'

This is the line of code on line 434.
BinFile = BinFile & Chr(HexStringToInt(Mid(StringCPUIDx86EXE, i, 2)))

I'm running WinXP SP2.


Find the function IsWhiteSpace and change it to (i've changed the elseif statement)

Public Function IsWhiteSpace(char)
dim result
if (Len(char) = 0) then
result = false
ElseIf (Asc(char) = 32) then
result = True
Else
result = False
End if
IsWhiteSpace = result
End Function

and it will work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top