제어판의 전원 옵션 구현하기
제어판의 전원 옵션 메뉴에는 전원을 관리하기 위한 옵션들을 수정할 수 있습니다.
기본적으로 균형 조정, 고성능, 절전의 옵션이 존재합니다.
일부 노트북이나 대기업 PC의 경우 다른 옵션이 있을 수도 있습니다.
설정 변경에 들어가면 디스플레이 끄기 시간과 절전 모드로 진입하는 시간을 설정할 수 있습니다.
그리고 고급 전원 관리 옵션 설정 변경(C)를 누르면 세부 설정이 가능합니다.
이 설정을 직접 가져오고 수정할 수 있는 API가 제공됩니다.
Power Management Reference는 아래 링크를 통해서 확인할 수 있습니다.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373170(v=vs.85).aspx
실제 값을 가져오기 위한 간단한 코드는 다음과 같습니다.
#include <Windows.h>
#include <PowrProf.h>
#include <iostream>
#include <string>
const std::wstring GetPowerReadFriendlyName(const GUID* SchemeGuid, const GUID* SubGroupOfPowerSettingsGuid = &NO_SUBGROUP_GUID, const GUID* PowerSettingGuid = nullptr)
{
DWORD dwLength = 0;
std::wstring szName;
if (ERROR_SUCCESS == ::PowerReadFriendlyName(nullptr, SchemeGuid, SubGroupOfPowerSettingsGuid, PowerSettingGuid, nullptr, &dwLength))
{
UCHAR* szFriendlyName = new UCHAR[dwLength];
if (ERROR_SUCCESS == ::PowerReadFriendlyName(nullptr, SchemeGuid, SubGroupOfPowerSettingsGuid, PowerSettingGuid, szFriendlyName, &dwLength))
{
szName.assign((wchar_t*)szFriendlyName);
}
delete[] szFriendlyName;
}
return szName;
}
const std::wstring GetUnitSpecifier(const GUID* SubGroupOfPowerSettingsGuid, const GUID* PowerSettingGuid)
{
DWORD dwLength = 0;
std::wstring szUnitSpecifier;
if (ERROR_SUCCESS == ::PowerReadValueUnitsSpecifier(nullptr, SubGroupOfPowerSettingsGuid, PowerSettingGuid, nullptr, &dwLength))
{
UCHAR* szUnits = new UCHAR[dwLength];
if (ERROR_SUCCESS == ::PowerReadValueUnitsSpecifier(nullptr, SubGroupOfPowerSettingsGuid, PowerSettingGuid, szUnits, &dwLength))
{
szUnitSpecifier.assign((wchar_t*)szUnits);
}
delete[] szUnits;
}
return szUnitSpecifier;
}
int main()
{
std::wcout.imbue(std::locale(""));
// Get Active Scheme.
GUID* pActivePolicyGuid = nullptr;
if (ERROR_SUCCESS != ::PowerGetActiveScheme(nullptr, &pActivePolicyGuid))
return -1;
GUID activePolicyGuid = *pActivePolicyGuid;
::LocalFree(pActivePolicyGuid);
// Enumerate power settings directly under the activePolicyGuid
std::wcout << GetPowerReadFriendlyName(&activePolicyGuid) << std::endl;
for (ULONG ulIndex = 0; ; ++ulIndex)
{
GUID guidSetting;
DWORD dwSettingLen = sizeof(guidSetting);
DWORD nRtn = ::PowerEnumerate(nullptr, &activePolicyGuid, &NO_SUBGROUP_GUID, ACCESS_INDIVIDUAL_SETTING, ulIndex, (UCHAR*)&guidSetting, &dwSettingLen);
if (ERROR_MORE_DATA == nRtn || ERROR_FILE_NOT_FOUND == nRtn)
continue;
else if (ERROR_NO_MORE_ITEMS == nRtn)
break;
std::wcout << L"\t" << GetPowerReadFriendlyName(&activePolicyGuid, &NO_SUBGROUP_GUID, &guidSetting) << std::endl;
DWORD AcValueIndex = 0;
::PowerReadACValueIndex(nullptr, &activePolicyGuid, &NO_SUBGROUP_GUID, &guidSetting, &AcValueIndex);
std::wstring szUnitSpecifier = GetUnitSpecifier(&NO_SUBGROUP_GUID, &guidSetting);
std::wcout << L"\t\t" << AcValueIndex << szUnitSpecifier << std::endl;
}
// Enumerate SubGroup power settings
for (ULONG ulIndex = 0; ; ++ulIndex)
{
GUID guidSubGroup = GUID_NULL;
DWORD dwSubGroupLen = sizeof(guidSubGroup);
DWORD nRtn = ::PowerEnumerate(nullptr, &activePolicyGuid, nullptr, ACCESS_SUBGROUP, ulIndex, (UCHAR*)&guidSubGroup, &dwSubGroupLen);
if (ERROR_MORE_DATA == nRtn || ERROR_FILE_NOT_FOUND == nRtn)
continue;
else if (ERROR_NO_MORE_ITEMS == nRtn)
break;
std::wcout << GetPowerReadFriendlyName(&activePolicyGuid, &guidSubGroup) << std::endl;
// Enumerate Individual power settings
for (ULONG ulSubIndex = 0; ; ++ulSubIndex)
{
GUID guidSetting = GUID_NULL;
DWORD dwSettingLen = sizeof(guidSetting);
nRtn = ::PowerEnumerate(nullptr, &activePolicyGuid, &guidSubGroup, ACCESS_INDIVIDUAL_SETTING, ulSubIndex, (UCHAR*)&guidSetting, &dwSettingLen);
if (ERROR_MORE_DATA == nRtn || ERROR_FILE_NOT_FOUND == nRtn)
continue;
else if (ERROR_NO_MORE_ITEMS == nRtn)
break;
std::wcout << L"\t" << GetPowerReadFriendlyName(&activePolicyGuid, &guidSubGroup, &guidSetting) << std::endl;
// Get Current Setting Value
DWORD AcValueIndex = 0;
::PowerReadACValueIndex(nullptr, &activePolicyGuid, &NO_SUBGROUP_GUID, &guidSetting, &AcValueIndex);
std::wstring szUnitSpecifier = GetUnitSpecifier(&NO_SUBGROUP_GUID, &guidSetting);
std::wcout << L"\t\t" << AcValueIndex << szUnitSpecifier << std::endl;
}
}
return 0;
}
먼저 PowerGetActiveScheme()를 통해서 현재 설정(균형 조정, 고성능, 절전)의 GUID를 가져옵니다.
전원 설정은 세부적인 설정까지 GUID로 지정되어 있습니다.
PowerEnumerate()를 호출하면 설정을 열거할 수 있습니다.
처음 for문은 하위 그룹이 아닌 현재 설정의 바로 하위의 설정 값을 가져오기 위해서 입니다.
그 이후에 이제 하위 그룹 > 설정 값을 가져오기 위한 for문을 돌립니다.
GetPowerReadFriendlyName()는 GUID를 실제 설정 이름으로 변경합니다.
그리고 현재의 설정값은 PowerReadACValueIndex()를 통해서 인덱스를 가져올 수 있습니다.
배터리 사용시에는 PowerReadDCValueIndex()를 사용하면 됩니다.
PowerReadValueUnitsSpecifier()는 단위를 가져옵니다.
디스플레이 밝기 등에서는 %가 리턴됩니다.
실제 사용해보면 제어판의 전원 옵션보다 훨씬 많은 설정을 확인할 수 있습니다.
다만 일부 옵션에서 설정 이름을 정상적으로 가져오지 못하는 것이 확인되었습니다.
API를 좀 더 봐야할 것 같습니다.