Obtaining system information

Started by
7 comments, last by Spacemonkey49 14 years, 6 months ago
Does anyone know of a lib or classes, C++ or .Net based, which would allow me to obtain various system information? Mostly I'm after processor type, speed, number of physics and logical cores active and what level of SSE support they have and optionally cache details, memory bus and speed. Idealy I also need something which will work on XP onwards if possible. Anyone got any ideas on how I would get such information, or of any libs which could help obtain it?
Advertisement
http://stackoverflow.com/questions/188503/detecting-the-number-of-processors

Detecting SSE support is simple. Use __cpuid() and check the appropriate bits.
For XPSP3+ you have GetLogicalProcessorInformation.
-Mike
You might have a look at the Windows Management Instrumentation. That gives you access to a fair few bits of info.
From a chunk of my engine, will get CPU data (type, features, L1 & L2 cache size, number of processors, and the speed of each), physical RAM, and OS. Works on x64 and x86, but isn't widely tested:
static const unsigned PROCESSOR_UNKNOWN = 0;static const unsigned PROCESSOR_AMD = 1;static const unsigned PROCESSOR_INTEL = 2;//============================================================================// Error handler//============================================================================static void ErrorBox(const std::string& strError){	MessageBoxA(NULL, strError.c_str(), "Error", MB_ICONERROR);}//============================================================================// Read the CPU speed from the registry//============================================================================static DWORD ReadCPUSpeedFromRegistry(DWORD dwCPU){HKEY hKey;DWORD dwSpeed;	// Get the key name	char szKey[256];	_snprintf(szKey, sizeof(szKey),		"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d\\", dwCPU);	// Open the key	if(RegOpenKeyExA(HKEY_LOCAL_MACHINE,szKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)	{		return 0;	}	// Read the value	DWORD dwLen = 4;	if(RegQueryValueExA(hKey, "~MHz", NULL, NULL, (LPBYTE)&dwSpeed, &dwLen) != ERROR_SUCCESS)	{		RegCloseKey(hKey);		return 0;	}	// Cleanup and return	RegCloseKey(hKey);    return dwSpeed;}//============================================================================// Calculate and log the CPU speed and features//============================================================================static void LogCPU(){unsigned nHighestFeature;unsigned nHighestFeatureEx;int nBuff[4];char szMan[13];char szFeatures[256];unsigned nProcessorType;	// Get CPU manufacturer and highest CPUID	__cpuid(nBuff, 0);	nHighestFeature = (unsigned)nBuff[0];	*(int*)&szMan[0] = nBuff[1];	*(int*)&szMan[4] = nBuff[3];	*(int*)&szMan[8] = nBuff[2];	szMan[12] = 0;	if(strcmp(szMan, "AuthenticAMD") == 0)		nProcessorType = PROCESSOR_AMD;	else if(strcmp(szMan, "GenuineIntel") == 0)		nProcessorType = PROCESSOR_INTEL;	else		nProcessorType = PROCESSOR_UNKNOWN;	// Get highest extended feature	__cpuid(nBuff, 0x80000000);	nHighestFeatureEx = (unsigned)nBuff[0];	// Get processor brand name	if(nHighestFeatureEx >= 0x80000004)	{		char szCPUName[49];		szCPUName[0] = 0;		__cpuid((int*)&szCPUName[0], 0x80000002);		__cpuid((int*)&szCPUName[16], 0x80000003);		__cpuid((int*)&szCPUName[32], 0x80000004);		szCPUName[48] = 0;		for(int i=(int)strlen(szCPUName)-1; i>=0; --i)		{			if(szCPUName == ' ')				szCPUName = '\0';			else				break;		}		ELog::Get().SystemFormat("PERF    : CPU: %s (%s)\n", szCPUName, szMan);	}	else		ELog::Get().SystemFormat("PERF    : CPU: %s\n", szMan);	// Get CPU features	szFeatures[0] = 0;	if(nHighestFeature >= 1)	{		__cpuid(nBuff, 1);		if(nBuff[3] & 1<<0)			strcat(szFeatures, "FPU ");		if(nBuff[3] & 1<<23)			strcat(szFeatures, "MMX ");		if(nBuff[3] & 1<<25)			strcat(szFeatures, "SSE ");		if(nBuff[3] & 1<<26)			strcat(szFeatures, "SSE2 ");		if(nBuff[2] & 1<<0)			strcat(szFeatures, "SSE3 ");		// Intel specific:		if(nProcessorType == PROCESSOR_INTEL)		{			if(nBuff[2] & 1<<9)				strcat(szFeatures, "SSSE3 ");			if(nBuff[2] & 1<<7)				strcat(szFeatures, "EST ");		}		if(nBuff[3] & 1<<28)			strcat(szFeatures, "HTT ");	}	// AMD specific:	if(nProcessorType == PROCESSOR_AMD)	{		// Get extended features		__cpuid(nBuff, 0x80000000);		if(nHighestFeatureEx >= 0x80000001)		{			__cpuid(nBuff, 0x80000001);			if(nBuff[3] & 1<<31)				strcat(szFeatures, "3DNow! ");			if(nBuff[3] & 1<<30)				strcat(szFeatures, "Ex3DNow! ");			if(nBuff[3] & 1<<22)				strcat(szFeatures, "MmxExt ");		}		// Get level 1 cache size		if(nHighestFeatureEx >= 0x80000005)		{			__cpuid(nBuff, 0x80000005);			ELog::Get().SystemFormat("PERF    : L1 cache size: %dK\n", ((unsigned)nBuff[2])>>24);		}	}	// Get cache size	if(nHighestFeatureEx >= 0x80000006)	{		__cpuid(nBuff, 0x80000006);		ELog::Get().SystemFormat("PERF    : L2 cache size: %dK\n", ((unsigned)nBuff[2])>>16);	}	// Log features	ELog::Get().SystemFormat("PERF    : CPU Features: %s\n", szFeatures);	// Get misc system info	SYSTEM_INFO theInfo;	GetSystemInfo(&theInfo);	// Log number of CPUs and speeds	ELog::Get().SystemFormat("PERF    : Number of CPUs: %d\n", theInfo.dwNumberOfProcessors);	for(DWORD i=0; i<theInfo.dwNumberOfProcessors; ++i)	{		DWORD dwCPUSpeed = ReadCPUSpeedFromRegistry(i);		ELog::Get().SystemFormat("PERF    : * CPU %d speed: ~%dMHz\n", i, dwCPUSpeed);	}}//============================================================================// Calculate and log the amount of RAM in the machine//============================================================================static void LogRAM(){	// Get memory status	MEMORYSTATUS theStatus;	ZeroMemory(&theStatus,sizeof(theStatus));	theStatus.dwLength = sizeof(theStatus);	GlobalMemoryStatus(&theStatus);	// Log it	DWORD dwRAM = (DWORD)(theStatus.dwTotalPhys/(1024*1024));	if(theStatus.dwTotalPhys != dwRAM*1024*1024)		++dwRAM;	ELog::Get().SystemFormat("PERF    : Available physical RAM: %dMB/%dMB\n",		theStatus.dwAvailPhys/(1024*1024), dwRAM);}//============================================================================// Determine OS type//============================================================================static void LogOS(){char szOS[256];OSVERSIONINFOEXA osInfo;SYSTEM_INFO sysInfo;	// Get system info	ZeroMemory(&sysInfo, sizeof(sysInfo));	GetSystemInfo(&sysInfo);	// Get OS version	strcpy(szOS, "PERF    : OS: ");	ZeroMemory(&osInfo, sizeof(osInfo));	osInfo.dwOSVersionInfoSize = sizeof(osInfo);	if(!GetVersionExA((OSVERSIONINFOA*)&osInfo))	{		ZeroMemory(&osInfo, sizeof(osInfo));		osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);		GetVersionExA((OSVERSIONINFOA*)&osInfo);	}	// Win 9x	if(osInfo.dwPlatformId == 1)	{		if((osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 0))			strcat(szOS, "Windows 95 ");		else if((osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 10))			strcat(szOS, "Windows 98 ");		else if((osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 90))			strcat(szOS, "Windows ME ");		else			strcat(szOS, "Unknown Windows OS ");	}	// Win NT	else if(osInfo.dwPlatformId == 2)	{		if((osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 0))			strcat(szOS, "Windows NT 4.0 ");		else if((osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion == 0))			strcat(szOS, "Windows 2000 ");		else if((osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion == 1))			strcat(szOS, "Windows XP ");		else if((osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion == 2))		{			if(GetSystemMetrics(89))	// SM_SERVERR2 == 89				strcat(szOS, "Windows Server 2003 R2 ");			else if((osInfo.wProductType == VER_NT_WORKSTATION) &&				(sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64))			{				strcat(szOS, "Windows XP Professional x64 Edition ");			}			else				strcat(szOS, "Windows Server 2003 ");		}		else if((osInfo.dwMajorVersion == 6) && (osInfo.dwMinorVersion == 0))			strcat(szOS, "Windows Vista ");		else			strcat(szOS, "Unknown WinNT OS ");	}	// Unknown	else		strcat(szOS, "Unknown Operating System ");	strcat(szOS, osInfo.szCSDVersion);	strcat(szOS, "\n");	// Log	ELog::Get().SystemLog(szOS);#if defined(BUILD_X64)	ELog::Get().SystemLog("PERF    : Win64 version\n");#elif defined(_WIN32)	ELog::Get().SystemLog("PERF    : Win32 version\n");#else	ELog::Get().SystemLog("PERF    : Unknown version\n");#endif}
Cheers for the info guys; I did know about __cpuid however that was looking like going into a murky world of familys, models and all manner of sillyness just to figure out what type of processor I was on.

Cheers for the code EvilSteve; makes me wonder why I didn't think about poking around in the registry before now myself [oh]

Quote:Original post by phantom
makes me wonder why I didn't think about poking around in the registry before now myself [oh]

Because then you'd be using undocumented information (I'm pretty sure) that may change form, disappear, or be a lie because so many apps break when any of the former happen. And then people blame Microsoft of course.
-Mike
Well, it doesn't need long term maintainance, just needs to work long enough for me to gain information from people for data generation thus pulling a few details from the registry, maybe with the __cpuid carried along as well.
Evil, this is probably going to seem like a retarded question so excuse me as I am new to this, but when I attempt to run this in Visual Studio 2008 I get errors relating to ELog based lines, presumably because I haven't included it for it to be able to call the functions included in it, can I just replace these lines with a standard output stream?

Nevermind, I tried using a standard output stream and it didn't work, so I guess my question is: Is there a way to output this information if I am running it as a win32 console application through Visual Studio 2008.

[Edited by - Spacemonkey49 on October 15, 2009 12:30:47 PM]

This topic is closed to new replies.

Advertisement