Click here to Skip to main content
15,867,771 members
Articles / Programming Languages / C++

Determine Information about System, User, Processes, Hardware...

Rate me:
Please Sign up or sign in to vote.
4.71/5 (18 votes)
6 Oct 2010CPOL14 min read 71.1K   72   18
The never ending 'How do I find' article. Will be updated regularly!

And it begins!

This article is compilation of all "How To Determine" list. For example "How to find the computer name", "how to find number of fonts installed on system". As you know the list is endless, and this would be regularly updated, updated on reader's demands and as new technology evolve.

Every effort it taken to use both C++ and C#. C++ code will be on top of native Windows API, and optionally using MFC. C# code will be on top of .NET framework, and if not available using DllImports of native Windows API. Content and examples on .NET may get delayed, but they would be added on regular basic. For all "how-to-retrieve" operation, there would be C++. For C++, wherever applicable, Unicode strings and functions are used.

No error checking is done in code snippets shown below. In projects attached, basic error checking is done.

Following is list of all "how-to" that is explained in this article. Linked or Bold content is mentioned here, and other how-to is scheduled for discussion. As the article would grow up, I would logically structure it.

Retrieve Current Date and Time

  • C++

There are multiple ways to retrieve the date/time. It depends if you need System Time (UTC), or the local time; the precision level of time and the preference with the time-retrieval function.

To retrieve Local Time, use can use GetLocalTime API, which would return time adjusted as per your location. This is the date/time you see everywhere and should display to end user. It retrieves local-time in SYSTEMTIME structure:

void</span /> DisplayCurrentTimeLocal()
{
   SYSTEMTIME stLocal;
   
   GetLocalTime(&stLocal);

   //</span /> Raw display in YYYY-MM-DD, HH:MM:SS.ms format
</span />   _tprintf( _T("</span />Local Time: %d-%02d-%02d, %02d:%02d:%02d.%03d"</span />), 
        stLocal.wYear, stLocal.wMonth, stLocal.wDay, //</span /> Date
</span />        stLocal.wHour, stLocal.wMinute, stLocal.wSecond, stLocal.wMilliseconds); 
}

You may retrieve non-adjusted System Time using GetSystemTime API. A UTC time may be useful for time-stamping in file or database, or to let Time travel across globe with consistency. It also takes SYSTEMTIME structure.

void</span /> DisplayCurrentTimeSystem() 
{
   SYSTEMTIME stSystem;
   GetSystemTime(&stSystem);

   _tprintf( _T("</span />UTC Time: %d-%02d-%02d, %02d:%02d:%02d.%03d"</span />), 
      stSystem.wYear, stSystem.wMonth, stSystem.wDay, //</span /> Date
</span />      stSystem.wHour, stSystem.wMinute, stSystem.wSecond, stSystem.wMilliseconds);
}

My friendly MFC programmers can use static method of CTime, named GetCurrentTime, which returns a CTime object. This class provides many Get functions to retrieve different components of date/time. The method Format, which formats the time as per the format string given (same as strftime), can be used to generate user friendly time.

void</span /> DisplayCurrentTimeMFC()
{
   CTime theTime;
   CString sFormattedTime;

   theTime = CTime::GetCurrentTime();

   sFormattedTime = theTime.Format( _T("</span />Today is %A, %B %d, %Y. And the time is %I:%M %p"</span />));

   _tprintf(L"</span />%s"</span />, sFormattedTime); 
   //</span /> Today is Saturday, October 02, 2010. And the time is 10:31 AM
</span />}

Though not the time par se, GetTickCount[64] can be used to retrieve number of milliseconds elapsed since system was started. The old version, GetTickCount, can work flawlessly up to 49.7 days. For Windows Vista and higher OS, you should use GetTickCount64.

The C Runtime Library lovers can use _ftime and _ftime_s family of functions to retrieve current System Time; and localtime and localtime_s family of functions to retrieve Local Time. The time family of functions returns number of seconds elapsed* since 1-Jan-1970 midnight. All these functions internally use GetSystemTimeAsFileTime.

Though not mentioned in MSDN, all other Windows API functions also use GetSystemTimeAsFileTime to retrieve current system time. GetSystemTimeAsFileTime calls the not exposed (via header/library) function NtQuerySystemTime. The function GetSystemTimeAsFileTime returns the most precise time among all other functions. It presumably returns timing in 100-nanoseconds precision. The precision depends on the hardware, the Operating System and the timing resolution set by calling process (use undocumented NtSetTimerResolution to set timer/timing resolution).

Go Top

With .NET framework, you can use the shared/static property Now of DateTime class to retrieve Local Time. The DateTime class is capable of producing time in precision of 100-nanoseconds.

//</span /> This method, and other upcoming methods are in InfoObtainer class.
</span />//</span /> The source code attached has complete code of InfoObtainer.
</span />
void</span /> DisplayLocalTime()
{
   //</span /> Get local time
</span />   DateTime dtCurrentTime = DateTime.Now;

   Console.WriteLine("</span />Local time (system formatted): {0}"</span />,dtCurrentTime);

   Console.WriteLine("</span />Local time: {0:D4}-{1:D2}-{2:D2}, {3:D2}:{4:D2}:{5:D2}.{6:D3}"</span />,
         dtCurrentTime.Year, dtCurrentTime.Month, dtCurrentTime.Day,
         dtCurrentTime.Hour, dtCurrentTime.Minute, 
         dtCurrentTime.Second, dtCurrentTime.Millisecond);
}

Likewise, to retrieve the System Time in UTC, you can use the static property UtcNow.

void</span /> DisplaySystemTime()
{
   //</span /> Retrieve system time 
</span />   DateTime dtCurrentTime = DateTime.UtcNow;
   
   Console.WriteLine("</span />System time (system formatted): {0}"</span />,dtCurrentTime);

   Console.WriteLine("</span />System time: {0:D4}-{1:D2}-{2:D2}, {3:D2}:{4:D2}:{5:D2}.{6:D3}"</span />,
         dtCurrentTime.Year, dtCurrentTime.Month, dtCurrentTime.Day,
         dtCurrentTime.Hour, dtCurrentTime.Minute, 
         dtCurrentTime.Second, dtCurrentTime.Millisecond);
}

To retrieve only the date, you can use static property Today, which keeps the time component to be 00:00:00. The date component is retrieve out of Local Time, and not of System Time.

Just for completeness, the public property Kind (of type DateTimeKind) can be used to know if time represented by DateTime object is local, system or undefined type. Thus, when you retrieve local date/time using Now or Today, it would be DateTimeKind.Local; and when you retrieve it using UtcNow, it would be DateTimeKind.Utc. This kindness is available in .NET Framework 2.0 and above.

The Ticks property returns number of 100-nanoseconds for this instance. A Tick is actually 0.1 microsecond, or 1/10000 (0.0001) milliseconds. Ticks property is 64-bit integer. The following code calculates the microseconds out of 100-nanoseconds, and displays.

DateTime dtCurrentTime = DateTime.Now;

//</span /> Get microseconds
</span />double</span /> nMicroSecs = ( dtCurrentTime.Ticks % 10000</span /> ) / 10</span />.0</span />;

Console.WriteLine("</span />Time: {0:D2}:{1:D2}:{2:D2}, {3:D3}:{4:F1}"</span />,
     dtCurrentTime.Hour, dtCurrentTime.Minute, dtCurrentTime.Second,
     dtCurrentTime.Millisecond, nMicroSecs);

Go Top

Retrieve Logged-in Username

  • C++

Technically it's not the username who is logged in, but the process or thread which is running under a user. A user or programmer may launch a process into another logon-credential using "RunAs" verb, or spawn a process using CreateProcessAsUser function. A running thread might be impersonated using ImpersonateLoggedOnUser API, or other impersonating functions. Well, this section is not about these tricks, but to retrieve the username under which current thread is running (or impersonating).

You can use GetUserName function to retrieve only the username.

void</span /> DisplayUserName()
{
   //</span /> UNLEN (256) is defined in lmcons.h
</span />   TCHAR Username[UNLEN+1];
   DWORD nULen = UNLEN;

   GetUserName(Username, &nULen); 

   _tprintf( _T("</span />Username: %s"</span />), Username);
   //</span /> Username: Ajay
</span />}

To retrieve fullname of user, you need to use GetUserNameEx function. This function is declared in header Security.h (actually in secext.h), thus you must #include<Security.h>. Including this header requires either of these to be defined:

  • SECURITY_WIN32
  • SECURITY_KERNEL
  • SECURITY_MAC

Since our application is Windows' User-mode application, use just define the first one. Further, we need to include the library Secur32.lib in Linker settings. Anyway, here is code:

#define</span /> SECURITY_WIN32
#include <Security.h>
//</span /> Link with secur32.lib
</span />
void</span /> DisplayUserNameEx()
{
   TCHAR Username[UNLEN+1];
   DWORD nULen = UNLEN;

   GetUserNameEx(NameSamCompatible, Username, &nULen); 
   _tprintf( _T("</span />Username: %s"</span />), Username);
}

Yes, GetUserNameEx takes one extra parameter, which is of EXTENDED_NAME_FORMAT enum type. The symbol NameSamCompatible is one of them enum of this type. On non-domain connected computers, only this enum is supported. Please explore other members of EXTENDED_NAME_FORMAT yourself, with which you can retrieve full name of user, the display name, the GUID of user; to name a few. The following is output of above' code:

Username: HERCULES\Ajay

Following is just for relevant discussion. As you know a process may be running in another Logon Session (i.e. sharing the Desktop/Console of other user), and the methods described above would just locate the username and not any information about the session under which process/thread is running. Whilst, I would elaborate about this sooner or later, the function you can use is: WTSGetActiveConsoleSessionId.

Go Top

.NET programmers can use Environment.UserName property to retrieve only the username. The Environment.UserDomainName property retrieves the domain name associated with current process/thread.

void</span /> DisplayUserName()
{
   Console.Write("</span />Domain of user is: "</span />);
   Console.WriteLine(Environment.UserDomainName); //</span /> HERCULES
</span />
 
   Console.Write("</span />User name is: "</span />);
   Console.WriteLine(Environment.UserName); //</span /> Ajay
</span />}

Please see MSDN documentation on how domain-name retrieval works. You can use following to retrieve both username and domain name in DOMAIN/USERNAME format:

string sFullyQualified = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

Console.WriteLine("</span />Fully qualified username: {0}"</span />, sFullyQualified);

See WindowsIdentity.Name property for more information.

Unfortunately, .NET Framework doesn't support equivalent routine for GetUserNameEx. Therefore, you must import this function:

//</span /> using System.Runtime.InteropServices;
</span />
public</span /> enum</span /> EXTENDED_NAME_FORMAT
{
   NameUnknown = 0</span />,
   NameFullyQualifiedDN = 1</span />,
   NameSamCompatible = 2</span />,
   NameDisplay = 3</span />,
   NameUniqueId = 6</span />,
   NameCanonical = 7</span />,
   NameUserPrincipal = 8</span />,
   NameCanonicalEx = 9</span />,
   NameServicePrincipal = 10</span />,
   NameDnsDomain = 12</span />
}
 
[DllImport("</span />secur32.dll"</span />, CharSet = CharSet.Auto)]
public</span /> static</span /> extern</span /> int</span /> GetUserNameEx(EXTENDED_NAME_FORMAT nameFormat, 
           StringBuilder userName,
           ref</span /> uint</span /> userNameSize);

And you can call this imported function like this:

StringBuilder userName = new</span /> StringBuilder(1024</span />);
uint userNameSize = 1024</span />;

GetUserNameEx(EXTENDED_NAME_FORMAT.NameSamCompatible, userName, ref</span /> userNameSize);

Console.Write(userName);

This code is derived from PInvoke.Net.

Go Top

Retrieve the name of Computer

  • C++

Use GetComputerName to retrieve the name of computer.

void</span /> DisplayComputerName()
{    
   TCHAR  szComputerName[MAX_COMPUTERNAME_LENGTH+1];
   DWORD  lnNameLength= MAX_COMPUTERNAME_LENGTH;

   GetComputerName( szComputerName, &lnNameLength);

   _tprintf( L"</span />\nComputer name:  %s\n"</span />, szComputerName); //</span /> HERCULES
</span />}

To get computer name in different formats you can use GetComputerNameEx function. Since my personal machine is not connected to any domain, it would always show the same name, or would return empty name when I call GetComputerNameEx with different format specifiers. Anyway, here is sample code.

void</span /> DisplayComputerNameEx()
{
   //</span /> Computer names may be larger than this macro, just
</span />   //</span /> doubling the buffer size. See MSDN for more info.
</span />   TCHAR scComputerName[MAX_COMPUTERNAME_LENGTH*2 + 1</span />];
   DWORD lnNameLength = MAX_COMPUTERNAME_LENGTH*2;
 
   GetComputerNameEx(ComputerNameNetBIOS, scComputerName, &lnNameLength);
        
   _tprintf( _T("</span />Computer name: %s\n"</span />), scComputerName);
}

The symbol ComputerNameNetBIOS is one of the symbols of enum type COMPUTER_NAME_FORMAT.

Go Top

Use Environment.MachineName property to get the name of computer. Example:

public</span /> void</span /> DisplayComputerName()
{
   Console.Write("</span />Computer name is: "</span />);
   Console.WriteLine(Environment.MachineName);
}

You can also use System.Net.Dns.GetHostName to retrieve the same.

The .NET framework does not support equivalent to GetComputerNameEx, thus you must import this function. For brevity, I am not showing code how to import. See GetUserNameEx import sample above.

Go Top

Retrieve the Number of Processors

  • C++

The function GetSystemInfo can be used to retrieve number of logical processors installed on system, including other processor related information. The GetSystemInfo takes SYSTEM_INFO and fills it. Following code displays number of processors installed on system.

void</span /> DisplayProcessorCount()
{
   SYSTEM_INFO sysInfo;
   GetSystemInfo(&sysInfo);

   _tprintf( _T("</span />Number of processors: %d"</span />), sysInfo.dwNumberOfProcessors);
}

Go Top

In .NET, it is fairly easy to retrieve logical processor count. Just use Environment.ProcessorCount property.

Console.WriteLine("</span />Processor count: {0}"</span />,  Environment.ProcessorCount);

Go Top

Retrieve Information about Hard Drives

This section about Hard Drive volumes and capacities, not about harddisk devices.

  • C++

Information about hard drives may include the following:

  • The drives present on the system (Volumes names like C:, D: etc.)
  • The type of each volume present (CDROM, Hard drive, USB drive etc.)
  • The capacity, allocated and free bytes on the drive.
  • The file system of specified volume (FAT32, NTFS etc)

Let's start by listing the volumes present in the system, like you see in Windows Explorer. For this you can use GetLogicalDrives and GetLogicalDriveStrings functions.

GetLogicalDrives returns a 32-bit (DWORD) value, which is just is just mask of drives present on system. For example, if a system as A:, C: and D: drives, the return values would be 13, which is, in binary 1101. The last bit digit in binary represents that system as A: drive, and so on. Following is simplified approach to get and display drive letters.

void DisplayDrives()
{
   DWORD dwDrivesMap = GetLogicalDrives();

   // Start with A: drive
   char cDrive='A';
   
   for (DWORD dwBitMask = 1; dwDrivesMap != 0;)
   {
      if (dwDrivesMap & dwBitMask)
      {
         _tprintf( _T("%c: drive present\n"), cDrive);

        // Discard this bit from DrivesMap
        dwDrivesMap &= ~dwBitMask;
      }
  
      // Next letter
      cDrive++;
   
     // Move to next (1, 2, 4, 8..32...128...)
     dwBitMask *= 2 ; // OR dwBitMask <<= 1; 
   }
}

This may not be intuitive for most readers. The another function GetLogicalDriveStrings, generates set of null terminated strings, with two null terminated characters at end. As you can guess this misfortune, this function is also not straightforward. Here is an example that displays drives.

void DisplayDriveStrings()
{
   TCHAR szDrives[MAX_PATH+1];
  
   GetLogicalDriveStrings(MAX_PATH, szDrives);

   TCHAR* pLetter = szDrives;
   while(*pLetter)
   {
     _tprintf( _T("Drive %s present\n"), pLetter);
     // _tprintf( _T("Drive %c: present\n"), *pLetter);

     // Find the null terminator for this string
     while(*++pLetter) ;  // Notice Semi-colon!
  
     // And the next *possible* drive letter,
     // Or get the termination of all drive letters.
     pLetter++;
  }
}

Okay, now let determine the type of drive (not the file-system). The type could be hard-disk drive, CDROM drive, Network drive, USB drive etc. First, I would explore simple function named GetDriveType, which returns one of the seven values (see the link mentioned). The following example shows how to process the drive type (only two types are processed).

void DisplayDriveTypes()
{
   TCHAR szDrives[MAX_PATH+1];
   DWORD dwLen = GetLogicalDriveStrings(MAX_PATH, szDrives);
   TCHAR* pLetter = szDrives;
   while(*pLetter)
   {
      UINT nType = GetDriveType(pLetter);
      _tprintf( _T("Drive %c: is "), *pLetter);
      switch(nType)
      {
        case DRIVE_FIXED:
           _tprintf( _T("Fixed Drive.\n") );
           break;
   
        case DRIVE_CDROM:
           _tprintf( _T("CD/DVD Drive.\n") );
           break;
        
        // Process other types
     }
 
     while(*++pLetter) ;  // Notice Semi-colon!
     pLetter++;
   }
}

This function cannot determine extended information, like if drive is USB drive. For this we need to use SetupDiGetDeviceRegistryProperty function, which is declared in setupapi.h, exported via library setupapi.lib and resides in setupapi.dll. It is available on Windows 2000 and later systems. I am taking your implicit permission to delay writing about it, since it requires some effort on the Setup API ground.

Meanwhile, we proceed and now let's find out about capacity of drives. For this, we can use GetDiskFreeSpace or GetDiskFreeSpaceEx function. Former does not support reporting information above 2GB, thus should not be used. Following example display the sizes of all enumerated drives.

void DisplayDriveSizes()
{
   TCHAR szDrives[MAX_PATH+1];
   DWORD dwLen = GetLogicalDriveStrings(MAX_PATH, szDrives);
   TCHAR* pLetter = szDrives;

   ULARGE_INTEGER liFree, liTotal;
   while(*pLetter)
   {
      //  Get size, ignoring disk-quotas.
      GetDiskFreeSpaceEx(pLetter, NULL, &liTotal, &liFree);

      // Display information
      _tprintf ( _T("Drive %c: has\n\tBytes Total: %I64u (%.2f GB)\n")
                 _T("\tBytes Available: %I64u (%.2f GB)\n\n"),
                 *pLetter, 
                 liTotal.QuadPart, liTotal.QuadPart / (float)(1<<30), 
                 liFree.QuadPart, liFree.QuadPart/(float)(1<<30) );

   
      while(*++pLetter);  
      pLetter++;
   }
}

Which would display something like:

Drive C: has
        Bytes Total: 58720251904 (54.69 GB)
        Bytes Available: 22550118400 (21.00 GB)
Drive D: has
        Bytes Total: 85899341824 (80.00 GB)
        Bytes Available: 43008344064 (40.05 GB)
Drive E: has
        Bytes Total: 341364961280 (317.92 GB)
        Bytes Available: 95171076096 (88.63 GB)

Finally let's retrieve File-System, Volume Label, Serial Number, Max File Length supported, and other Flags. For all this, you just need to use one function, GetVolumeInformation which takes eight parameters. The following code would help you to understand this function.

void DisplayVolumeInformations()
{
   TCHAR szVolume[MAX_PATH+1];
   TCHAR szFileSystem[MAX_PATH+1]; 
 
   DWORD dwSerialNumber, dwMaxLen, dwSystemFlags;
  
   // Same stuff!
   TCHAR szDrives[MAX_PATH+1];
   DWORD dwLen = GetLogicalDriveStrings(MAX_PATH, szDrives);
   TCHAR* pLetter = szDrives;

   BOOL bSuccess;
  
   while(*pLetter)
   {
      bSuccess = GetVolumeInformation(pLetter, // The source
                         szVolume, MAX_PATH,   // Volume Label (LABEL)
                         &dwSerialNumber,&dwMaxLen, // Serial Number (VOL)
                         &dwSystemFlags, 
                         szFileSystem, MAX_PATH); // File System (NTFS, FAT...)

      if(bSuccess)
      {
         _tprintf( _T("Information about volume %c:\n"), *pLetter);
        
         // LABEL command
         _tprintf( _T("\tVolume Label: %s\n"), szVolume);
        
         // Standard formal to display serial number (VOL command)
         _tprintf( _T("\tSerial Number: %X-%X\n"), 
                     HIWORD(dwSerialNumber), LOWORD(dwSerialNumber));

         // File-System
         _tprintf( _T("\tFile System: %s\n\n"), szFileSystem);
      }
      else
      {
         _tprintf ( _T("Cannot retrieve Volume information for %s\n\n"), pLetter);
      }
    
      while(*++pLetter) ;  // Notice Semi-colon!
      pLetter++;
   }
}

I have noticed that for CD/DVD drive, where no disc is inserted, this function fails. It cannot retrieve the information, since it is about drive/volume not about disk. It would present output in following form:

Information about volume C:
        Volume Label: Windows
        Serial Number: 24AE-237C
        File System: NTFS
 
Information about volume D:
        Volume Label: Stuff
        Serial Number: 40C5-2816
        File System: NTFS
 
Cannot retrieve Volume information for G:\

Information about volume T:
        Volume Label: Colossal
        Serial Number: 2292-7263
        File System: NTFS

Notice that Serial Number is just a 32-bit value, and I just printed lower 16-bits and upper 16-bits in hex, which is same as output given by VOL command.

Go Top

Retrieve Information about Memory

  • C++

To retrieve information about memory (RAM), you can either use GlobalMemoryStatus or GlobalMemoryStatusEx. They take MEMORYSTATUS and MEMORYSTATUSEX structures, respectively. The former has limitations and cannot return correct information on systems having more than 4GB, thus it should not be used. The following example shows how to get memory information, and displays it.

void</span /> DisplayMemoryStatus()
{
   MEMORYSTATUSEX memoryStatus;
   memoryStatus.dwLength = sizeof</span />(MEMORYSTATUSEX); //</span /> MUST!
</span /> 
   GlobalMemoryStatusEx(&memoryStatus);

   const</span /> float</span /> OneGB = 1024</span /> * 1024</span /> * 1024</span />; //</span /> (1<<30)
</span />   
   //</span /> In GBs
</span />   _tprintf( _T("</span />Total physical memory: %.2f GB\n"</span />)
             _T("</span />Available physical memory: %.2f GB\n"</span />)
             _T("</span />Pagefile size: %.2f GB"</span />),
             memoryStatus.ullTotalPhys / OneGB,
             memoryStatus.ullAvailPhys / OneGB,
             memoryStatus.ullTotalPageFile/OneGB);
}

Which would display something like:

Total physical memory: 3</span />.99</span /> GB
Available physical memory: 1</span />.69</span /> GB
Pagefile size: 7</span />.98</span /> GB

You should explore other members of this structure. One member of this structure is worth mentioning: dwMemoryLoad (DWORD), which returns percent of physical memory occupied. Thus, you need not to calculate the memory-load! For the above run, it was 57.

Go Top

There is no .NET framework class that supports direct information retrieval. Thus, you either need to import the GlobalMemoryStatusEx function or use the following approach:

const float</span /> OneGB = (1024</span /> * 1024</span /> * 1024</span />);

System.Management.ManagementObjectSearcher mos;

mos = new ManagementObjectSearcher("</span />SELECT TotalPhysicalMemory, FROM Win32_ComputerSystem"</span />);

foreach (ManagementObject mob in</span /> mos.Get())
{
   foreach (PropertyData pyd in</span /> mob.Properties)
   {
      if</span /> (pyd.Name == "</span />TotalPhysicalMemory"</span />)
      {
         Console.WriteLine("</span />Total Memory size: {0:F2}"</span />, 
             Convert</span />.ToInt64(pyd.Value) / OneGB);
         
         break;
      }
   }
}

Seriously, even I do not know about this stuff! I found it somewhere, and pasted here (after testing!). There are other approaches with System.Management to retrieve more of this type of information.

See this link on how to import native function and retrieve memory information. The same link (PInvoke.net) gives more clue about the same.

Go Top

Retrieve the Monitor Resolution

  • C++

First thing I should address - the "get monitor resolution" could mean multiple things depending on your need and perspective. These perspectives could be:

  • You need exact current resolution of monitor.
  • You need maximum client-area size for your application, that would exclude the taskbar.
  • You may need resolutions of multiple attached monitors/displays (if any).

Let's start with the first one - retrieve the actual current resolution of monitor. For this you need to use GetSystemMetrics function, passing SM_CXSCREEN and SM_CYSCREEN parameters, to get Width and Height of monitor's resolution.

void DisplayMonitorResolution()
{
   int nWidth = GetSystemMetrics(SM_CXSCREEN);
   int nHeight = GetSystemMetrics(SM_CYSCREEN);

   _tprintf( _T("Current Resolution is - Width: %d, Height: %d"), nWidth, nHeight);
   // Current Resolution is - Width: 1920, Height: 1080
}

You can retrieve the same information using GetDeviceCaps function, passing HORZRES and VERTRES arguments. This function requires you to pass a Device Context (HDC). This article won't describe about that, but I would just put the sample code to show how GetDeviceCaps can be used.

int nWidth  = GetDeviceCaps(GetDC(GetDesktopWindow()),  HORZRES);
int nHeight = GetDeviceCaps(GetDC(GetDesktopWindow()),  VERTRES);

Now, let's determines full-screen client area size. For this you need to use GetSystemMetrics function, passing SM_CXFULLSCREEN and SM_CYFULLSCREEN parameters, to get Width and Height of workable area. This size excludes two things: the size (width) of Title bar of window, and size of taskbar. While most users have taskbar on bottom of screen, thus Height would be smaller than actual resolution of monitor - but, taskbar can be on any side of monitor, it can be any size or it doesn't occupy the desktop (hidden or disabled). The following code displays the possible client area for a full-screen window:

void DisplayClientAreaSize()
{
   int nWidth = GetSystemMetrics(SM_CXFULLSCREEN);
   int nHeight = GetSystemMetrics(SM_CYFULLSCREEN);
 
   _tprintf( _T("Maximum Client Area - Width: %d, Height: %d"), nWidth, nHeight);
   // Maximum Client Area - Width: 1920, Height: 1028
}

Okay, in the same perspective, you might want to know how to get dimensions of a full-screen application that would include the taskbar, and exclude the size of Title bar. Any media player with skin support may need this.

For this you need to use SystemParametersInfo function with SPI_GETWORKAREA action parameter. Since this function supports wide range of retrievals, with varying data-types, it takes LPVOID (void*) as argument. For our action parameter, we need to pass address of a RECT structure. Here is code:

void DisplayFullScreenSize()
{
   RECT rectRes;
   SystemParametersInfo(SPI_GETWORKAREA, 0, &rectRes, 0);

   _tprintf( _T("Possible work area: Top = %d, Left = %d, Right = %d, Bottom = %d"),
        rectRes.top, rectRes.left, rectRes.right, rectRes.bottom);
}

It display following for my default resolution and normal size taskbar on bottom:

Possible work area: Top = 0, Left = 0, Right = 1920, Bottom = 1050

Well, you cannot ignore the top and left, since moving the taskbar on top would produce the following result (also, I doubled the task bar's size!):

Possible work area: Top = 62, Left = 0, Right = 1920, Bottom = 1080

Multiple monitors! To get information about monitors you need to use EnumDisplayMonitors, which would enumerate all monitors on system, via a callback. The callback would get HMONITOR, which can be passed to GetMonitorInfo function. GetMonitorInfo function would fill up MONITORINFO[EX], and that structure's member would have resolution of desire monitor! You see, this demands another section in this article, and I would soon put it!

Go Top

Retrieve the Windows Version

  • C++

You can use GetVersion or GetVersionEx to retrieve the Windows Version. The former function returns a 32-bit value, whose lower 16-bit represents the major and minor version numbers. The higher order 16 bits represents the build number. Following example illustrates this.

void DisplayWindowsVersion()
{
 DWORD dwWinVer;
 dwWinVer = GetVersion();

 
 _tprintf ( _T("Windows version: %d.%d.%d"),
            LOBYTE(LOWORD(dwWinVer)), HIBYTE(LOWORD(dwWinVer)),  // LoWord
            HIWORD(dwWinVer));
}

Which displays following output on my Windows 7 machine:

Windows version: 6.1.7600

GetVersion function has some concerns (not bugs), thus is is not suitable for recent applications. It cannot determine product information (Professional, Ultimate), service pack information etc, for example. It should not be used in new applications.

For new applications GetVersionEx function should be used. Exploring more about this function is beyond the scope of this article, only basic information is being provided. You should read this article on CodeGuru.com.

Just in brief; this function returns information in either OSVERSIONINFO or OSVERSIONINFOEX structure. No, this function is not overloaded - instead the dwOSVersionInfoSize member, which should be set to size of either of these structures, determines which type of information is requested.

void DisplayWindowsVersionEx()
{
   OSVERSIONINFOEX osvInfo ={0}; 
   osvInfo.dwOSVersionInfoSize = sizeof(osvInfo);
 
   // Need to typecast, function takes OSVERSIONINFO
   GetVersionEx( (OSVERSIONINFO*)&osvInfo );

   _tprintf( _T("Windows version: %d.%d\n"), 
             osvInfo.dwMajorVersion, osvInfo.dwMinorVersion);

   _tprintf( _T("Build: %d\n"), osvInfo.dwBuildNumber);

   _tprintf( _T("Product Type: ") );

   switch(osvInfo.wProductType)
   {
      case VER_NT_WORKSTATION:
           _tprintf( _T("Workstation\n") );
           break;
 
      case VER_NT_SERVER:
           _tprintf( _T("Server\n") );
           break;
 
      case VER_NT_DOMAIN_CONTROLLER:
          _tprintf( _T("Domain Controller\n") );
          break;
   }
}

There are other useful and interesting members of OSVERSIONINFOEX. Please look and do engineering with them yourself, or read the article link given above.

... But, it doesn't End!

Yes, this probably wont end in near future. I would keep it updated!

Stay Tuned!

History

  • Oct 3, 2010 - Initial posting. Date/Time, Username, Computer name, Processor Count, Memory Information and Monitor Resolution explored.
  • Oct 6, 2010 - Drives Information
  • Oct 7, 2010 - Volume Information, Windows Version
Every effort is taken to make all internal and external links workable. For internal links, the CodeProject's editor has some bugs and it removes the link. For external links, the web page may open in same window, though I made it to open in another window/tab. Thus, if you note external link being opened in same window/tab, please let me know.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
Started programming with GwBasic back in 1996 (Those lovely days!). Found the hidden talent!

Touched COBOL and Quick Basic for a while.

Finally learned C and C++ entirely on my own, and fell in love with C++, still in love! Began with Turbo C 2.0/3.0, then to VC6 for 4 years! Finally on VC2008/2010.

I enjoy programming, mostly the system programming, but the UI is always on top of MFC! Quite experienced on other environments and platforms, but I prefer Visual C++. Zeal to learn, and to share!

Comments and Discussions

 
GeneralVery good article ! Pin
LoveVc5-Oct-10 5:16
LoveVc5-Oct-10 5:16 
GeneralRe: Very good article ! Pin
Ajay Vijayvargiya5-Oct-10 5:51
Ajay Vijayvargiya5-Oct-10 5:51 
GeneralRe: Very good article ! Pin
vnt25-Oct-10 12:45
vnt25-Oct-10 12:45 
GeneralMy vote of 4 Pin
JackDanyelZ003-Oct-10 22:45
JackDanyelZ003-Oct-10 22:45 
GeneralMy vote of 4 Pin
Panic2k33-Oct-10 7:26
Panic2k33-Oct-10 7:26 
GeneralGood. But .. Pin
Muhammad Gouda3-Oct-10 6:32
Muhammad Gouda3-Oct-10 6:32 
GeneralRe: Good. But .. Pin
Ajay Vijayvargiya3-Oct-10 6:50
Ajay Vijayvargiya3-Oct-10 6:50 
GeneralRe: Good. But .. Pin
Member 1336696110-Dec-17 18:31
Member 1336696110-Dec-17 18:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.