Obtaining system information
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?
http://stackoverflow.com/questions/188503/detecting-the-number-of-processors
Detecting SSE support is simple. Use __cpuid() and check the appropriate bits.
Detecting SSE support is simple. Use __cpuid() and check the appropriate bits.
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]
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.
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]
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
Popular Topics
Advertisement