본문 바로가기
Programming/3. MFC

[API/MFC] 레지스트리 읽고 쓰는 함수

by S.W 2022. 12. 1.

Registry read, write.

레지스트리를 입력하거나 읽을려면 RegSetValueEX, RegQueryValueEx등을 써야하는데 들어가는 인자 셋팅하는게 귀찮다. 따라서 다음과 같이 쉽게 쓰도록 만들어주면 좋다.

우선 쓰기.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Registry에서 string value 쓰는 함수.
///
///     @param[in]  hKey        쓸 값이 존재하는 키, { HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, ...} 등의 값 사용.
///     @param[in]  lpSubKey    쓸 값이 존재하는 subkey path
///     @param[in]  lpValueKey  쓸 값의 이름
///     @param[in]  lpValue     쓸 값
///
///     \return     BOOL; 성공적으로 썼으면 TRUE 실패했으면 FALSE
///
/// \author JaeHyun Baek
BOOL MiscUtils::WriteStringValueInRegistry( HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueKey, LPCTSTR lpValue )
{
    CString strValue = _T("");
    HKEY hSubKey = NULL;
 
    // open the key
    if ( ::RegOpenKeyEx( hKey, lpSubKey, 0, KEY_ALL_ACCESS, &hSubKey ) == ERROR_SUCCESS )
    {
 
        DWORD cbSize = (DWORD)strlen(lpValue) + 1;
        BYTE *pBuf = new BYTE [ cbSize ];
        ::ZeroMemory( pBuf, cbSize );
        ::CopyMemory( pBuf, lpValue, cbSize - 1 );
        ::RegSetValueEx( hSubKey, lpValueKey, NULL, REG_SZ, pBuf, cbSize );
 
        // 키 닫기
        ::RegCloseKey( hSubKey );
 
        delete [] pBuf;
 
        return TRUE;
    }
 
    return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Registry에서 DWORD value 쓰는 함수.
///
///     @param[in]  hKey        쓸 값이 존재하는 키, { HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, ...} 등의 값 사용.
///     @param[in]  lpSubKey    쓸 값이 존재하는 subkey path
///     @param[in]  lpValueKey  쓸 값의 이름
///     @param[in]  dwValue     쓸 값
///
///     \return     BOOL; 성공적으로 썼으면 TRUE 실패했으면 FALSE
///
/// \author JaeHyun Baek
BOOL MiscUtils::WriteDWORDValueInRegistry( HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueKey, DWORD dwValue )
{
    CString strValue = _T("");
    HKEY hSubKey = NULL;

    // open the key
    if ( ::RegOpenKeyEx( hKey, lpSubKey, 0, KEY_ALL_ACCESS, &hSubKey ) == ERROR_SUCCESS )
    {
        ::RegSetValueEx( hSubKey, lpValueKey, NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD) );
 

        // 키 닫기
        ::RegCloseKey( hSubKey );
 
        return TRUE;
    }
 
    return FALSE;
}



그리고 읽기.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Registry에서 string value 읽어오는 함수.
/// CWinApp::GetProfileString(..) 함수와 다른 점은, 임의의 key 에 존재하는 값을 모두 읽을 수 있다는 점이 다름.<br>
 
/// 키가 존재하지 않으면 empty string을 리턴함.
///
///     @param[in]  hKey        읽을 값이 존재하는 키, { HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, ...} 등의 값 사용.
///     @param[in]  lpSubKey    읽을 값이 존재하는 subkey path
///     @param[in]  lpValueKey  읽을 값의 이름
///
///     \return     CString; 해당 레지스트리 위치에서 읽은 값. Can be null string
///
///
CString MiscUtils::ReadStringValueInRegistry( HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueKey )
{
    CString strValue = _T("");
    HKEY hSubKey = NULL;
 
    // open the key
    if ( ::RegOpenKeyEx( hKey, lpSubKey, 0, KEY_READ, &hSubKey ) == ERROR_SUCCESS )
    {
        DWORD buf_size = 0;
 
        // 문자열의 크기를 먼저 읽어온다.
        if ( ::RegQueryValueEx( hSubKey, lpValueKey, NULL, NULL, NULL, &buf_size ) == ERROR_SUCCESS )
        {
            // 메모리 할당하고...,
            TCHAR *pBuf = new TCHAR [ buf_size + 1 ];
 
            // 실제 값을 읽어온다.
            if ( ::RegQueryValueEx( hSubKey, lpValueKey, NULL, NULL, (LPBYTE)pBuf, &buf_size ) == ERROR_SUCCESS )
            {
                pBuf[ buf_size ] = _T('\0');
                strValue = CString( pBuf );
            }
 
            // to avoid leakage
            delete [] pBuf;
        }
 
        // 키 닫기
        ::RegCloseKey( hSubKey );
    }
 
    return strValue;
}
 

 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 임의의 레지스트리 키 위치에서 DWORD 값을 읽어오기 위한 함수.
/// CWinApp::GetProfileInt(..) 함수와 다른 점은, 임의의 key 에 존재하는 값을 모두 읽을 수 있다는 점이 다름.
 
/// 키가 존재하지 않으면 \a dwDefault 를 리턴함.
///
///     @param[in]  hKey        읽을 값이 존재하는 키, { HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, ...} 등의 값 사용.
///     @param[in]  lpSubKey    읽을 값이 존재하는 subkey path
///     @param[in]  lpValueKey  읽을 값의 이름
///     @param[in]  dwDefault   값이 존재하지 않는 경우에 리턴할 값
///
///     \return     DWORD; 해당 레지스트리 위치에서 읽은 값
///
DWORD MiscUtils::ReadDWORDValueInRegistry( HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueKey, DWORD dwDefault /*= -1*/ )
{
    DWORD dwValue = (DWORD)dwDefault;
    HKEY hSubKey = NULL;
 
    // 키 열기
    if ( ::RegOpenKeyEx( hKey, lpSubKey, 0, KEY_READ, &hSubKey ) == ERROR_SUCCESS )
    {
        DWORD buf_size = sizeof(DWORD);
 
        // DWORD 값 읽어오기
        if ( ::RegQueryValueEx( hSubKey, lpValueKey, NULL, NULL, (LPBYTE)&dwValue, &buf_size ) == ERROR_SUCCESS )
        {
            ASSERT( buf_size == sizeof(DWORD) );
        }
 
        // 키 닫기
        ::RegCloseKey( hSubKey );
    }
 
    return dwValue;
}



이제 실제 사용 하는 것은 다음과 같은 식으로 해주면 된다.

const CString strKey = _T("SOFTWARE\RoterSoft\ExampleApp\Settings");
MiscUtils::WriteStringValueInRegistry( HKEY_LOCAL_MACHINE, (LPCTSTR) strKey, _T("strTest"), _T("roterpekr"));
MiscUtils::WriteDWORDValueInRegistry( HKEY_LOCAL_MACHINE, (LPCTSTR) strKey, _T("dwTest"), 123456);



첫 번째 인자인 hKey는 다음을 알아서 넣어 주면 된다.

#define HKEY_CLASSES_ROOT           (( HKEY ) (ULONG_PTR)((LONG)0x80000000) )
#define HKEY_CURRENT_USER           (( HKEY ) (ULONG_PTR)((LONG)0x80000001) )
#define HKEY_LOCAL_MACHINE          (( HKEY ) (ULONG_PTR)((LONG)0x80000002) )
#define HKEY_USERS                  (( HKEY ) (ULONG_PTR)((LONG)0x80000003) )