Archive: Can I detect the number of CPUs in a multiprocessor machine?


Can I detect the number of CPUs in a multiprocessor machine?
I just started working with the NSIS and I love its power and flexibility, but I have a question. I was wondering if there's any way to detect the number of processors in a computer. It seems like it might be possible using the System plugin, but I can't figure out how. If anyone has experience in this area, I'd sure appreciate any help you can offer.

Thanks in advance!

-Y


See the MSDN documentation for information about the GetSystemInfo API.


Cool, thanks so much for your help! I apologize in advance for asking what I'm sure is an obvious questions, but my background is in PHP scripting so this Windows API stuff is pretty foreign to me.

Anyway, I researched this and found that GetSystemInfo returns information in the following order: OEM ID, page size, minimum application address, maximum application address, active cpu mask, number of cpus, cpu type, allocation granularity, reserved. Given this, is my code to store the number of CPUs in $1 correct?

System::Alloc 32
Pop $0
System::Call "Kernel32::GetSystemInfo(i) v (r0)"
System::Call "*$0(v,v,v,v,v,&i4 .r1)"
System::Free $0

I tested this and I'm pretty sure it returns the right value. However, I wrote it from bits and pieces of other examples I found around the net and I'm not sure exactly what I'm doing. What I really want to know is whether the code is sloppy, or if it's 'correct' for what I'm trying to do. Hopefully someone with a little more experience using the system plugin to call DLLs can tell me whether I should make any changes.

Thanks again,

-Y


SYSTEM_INFO is 36 bytes so you should allocate 36 bytes and not 32. Other than that, it all seems correct, thought just to be sure I'd replace all the v's on line 4 with i's, because it is DWORD and not void.


Awesome! That's just what I needed to know. Thanks both of you for all your help.

-Y


why 36?, please give a explanation?


Originally posted by vicokoby
why 36?, please give a explanation?
The size of SYSTEM_INFO on a 32 bit system

How can I get the architecture?


;This is my try to get the Processor Architecture:

System::Alloc 32
Pop $0
System::Call "Kernel32::GetSystemInfo(i r0)"
System::Call "*$0(i, &i2 .r1)"
System::Free $0
DetailPrint "Processor Architecture: $1" ; This print 4096 but it not a valid value!


Please help me!

This whole thread is about using 36 as the size and you continue to use 32???


Sorry,

Wich is the size in a 64 bit System?


Originally posted by vicokoby
Sorry,

Wich is the size in a 64 bit System?
NSIS is still 32bit. (If you wanted to call GetNativeSystemInfo, then the info might change but this thread is not about the native version)

Thanks!


There is still problem with this code. I tested the following lines (allocated memory is 36 bytes):

System::Alloc 36
Pop $0
${If} $0 <> 0
MessageBox MB_OK "Allocation done!"
System::Call "Kernel32::GetSystemInfo(i r0)"
System::Call "*$0(i, &i2 .r1)"
System::Free $0
${Else}
MessageBox MB_OK "Allocation failed!"
${EndIf}
MessageBox MB_OK "Results: $1" ; The result is 4096 (tested on XP and 7)

Why the result in $1 is always 4096? Little help, please!!!


You're trying to detect the system architecture? Just use x64.nsh.

Stu


System::Call "*$0(i, &i2 .r1)"
That code makes no sense at all, you are grabbing a invalid field by doing this.

Originally Posted by Afrow UK You're trying to detect the system architecture? Just use x64.nsh.

Stu
I already done it and it works, but I just want to understand why I can not make it with the function GetSystemInfo().

Originally Posted by Anders That code makes no sense at all, you are grabbing a invalid field by doing this.
Yes, I saw this (sorry that I didn't mentioned it). I need the first word from the union in the beginning of the structure of type SYSTEM_INFO, because:

typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId;
struct {
WORD wProcessorArchitecture;
WORD wReserved;
};
};
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision;
} SYSTEM_INFO;

So if I understood correct the syntax, I have to use:

System::Call "*$0(&i2 .r1)"

I tried this and I tried also:

System::Call "*$0(i .r1)"

... and I always get 4096. Where is my mistake? When I try to get dwNumberOfProcessors and dwProcessorType, I see meaningful values.

The correct call is:
System::Call `*$0(&i2 .r1)`

However you will always get 0 because NSIS is 32-bit (that's what I get with the above). The correct way is how x64.nsh does it in the _RunningX64 macro.

Stu