Last active
April 25, 2020 09:52
-
-
Save asquigglytwist/545f6a87507154ebb030225d474647dc to your computer and use it in GitHub Desktop.
Perform PreFlight Checks (like Min OS, Min RAM, Min FreeDiskSpace) on Windows - typically performed before any business logic.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#ifndef PREFLIGHTCHECK_HPP | |
#define PREFLIGHTCHECK_HPP | |
/* References for this implementation: | |
https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex | |
https://stackoverflow.com/questions/20119643/stringizing-operator-in-c-c | |
https://stackoverflow.com/questions/46794133/how-to-perform-arthemetic-with-ularge-integer | |
*/ | |
#include "stdafx.h" | |
#include <Windows.h> | |
#include <VersionHelpers.h> | |
#define STRINGIFY(X) tstring(_T(#X)) | |
#define HANDLE_RETURN_CODE(NameOfCheck, ReturnValue) { if (CheckReturnValue::UnableToPerformCheck == ReturnValue || CheckReturnValue::Fail == ReturnValue) { checkThatFailed = STRINGIFY(NameOfCheck); return ReturnValue; } } | |
#define ADD_CHECK(NameOfCheck) { HANDLE_RETURN_CODE(KnownPreFlightChecks::##NameOfCheck, EnvMeets##NameOfCheck()); } | |
#define WIDTH 7 | |
#define BYTES_PER_KB 1024 | |
#define BYTES_TO_KB(X) (X / BYTES_PER_KB) | |
#define BYTES_TO_MB(X) (BYTES_TO_KB(X) / BYTES_PER_KB) | |
#define BYTES_TO_GB(X) (BYTES_TO_MB(X) / BYTES_PER_KB) | |
#define MINIMUM_RAM_SIZE_IN_GB 2 | |
#define MINIMUM_FREE_SPACE_IN_GB 1 | |
namespace PreFlightCheck | |
{ | |
enum class KnownPreFlightChecks | |
{ | |
MinOSVersion, | |
MinRAMSize, | |
MinFreeDiskSpace | |
}; | |
enum class CheckReturnValue/* : int*/ | |
{ | |
UnableToPerformCheck = -2, | |
Fail = -1, | |
Pass | |
}; | |
auto EnvMeetsMinOSVersion() | |
{ | |
auto retVal = CheckReturnValue::UnableToPerformCheck; | |
if (IsWindows7OrGreater()) | |
{ | |
dprintf(_T("OS is Windows 7 or higher.")); | |
retVal = CheckReturnValue::Pass; | |
} | |
else | |
{ | |
// Vista SP2 or lower. | |
dprintf(_T("OS is lower than Windows 7.")); | |
retVal = CheckReturnValue::Fail; | |
} | |
return retVal; | |
} | |
auto EnvMeetsMinRAMSize() | |
{ | |
auto retVal = CheckReturnValue::UnableToPerformCheck; | |
MEMORYSTATUSEX memStatEx; | |
memStatEx.dwLength = sizeof(memStatEx); | |
if (::GlobalMemoryStatusEx(&memStatEx) == FALSE) | |
{ | |
dprintf(_T("Unable to check for RAM size; Error: [%ld]."), ::GetLastError()); | |
} | |
else | |
{ | |
auto ramSizeInKB = BYTES_TO_KB(memStatEx.ullTotalPhys); | |
auto ramSizeInGB = BYTES_TO_GB(memStatEx.ullTotalPhys); | |
dprintf(_T("Available Physical Memory: %*I64d in KB; %ld in GB."), WIDTH, ramSizeInKB, ramSizeInGB); | |
if (ramSizeInGB < MINIMUM_RAM_SIZE_IN_GB) | |
{ | |
retVal = CheckReturnValue::Fail; | |
} | |
else | |
{ | |
retVal = CheckReturnValue::Pass; | |
} | |
} | |
return retVal; | |
} | |
auto EnvMeetsMinFreeDiskSpace() | |
{ | |
ULARGE_INTEGER uliFreeDiskSpaceForCaller; | |
auto retVal = CheckReturnValue::UnableToPerformCheck; | |
if (::GetDiskFreeSpaceEx(nullptr, &uliFreeDiskSpaceForCaller, nullptr, nullptr) == FALSE) | |
{ | |
dprintf(_T("Unable to check for RAM size; Error: [%ld]."), ::GetLastError()); | |
} | |
else | |
{ | |
auto freeSpaceInGB = BYTES_TO_GB(uliFreeDiskSpaceForCaller.QuadPart); | |
dprintf(_T("freeSpaceInGB: %ud"), freeSpaceInGB); | |
if (freeSpaceInGB < MINIMUM_FREE_SPACE_IN_GB) | |
{ | |
retVal = CheckReturnValue::Fail; | |
} | |
else | |
{ | |
retVal = CheckReturnValue::Pass; | |
} | |
} | |
return retVal; | |
} | |
auto DoesEnvironmentMeetPreFlightCheckRequirements(tstring& checkThatFailed) | |
{ | |
ADD_CHECK(MinOSVersion); | |
ADD_CHECK(MinRAMSize); | |
ADD_CHECK(MinFreeDiskSpace); | |
return CheckReturnValue::Pass; | |
} | |
} | |
#endif // !PREFLIGHTCHECK_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment