A Class For Handling The Registry
Changes in Revision 3
Changes in Revision 4
Changes in Revision 5
Usage
Download
Often one can read in the newsgroups, that someone is looking for an MFC class that encapsulates the registry. In fact, MFC does not provide such a class. As long as one has no need to work with the registry in another location than HKEY_CURRENT_USER\Software\[<company>\]<product>, one can use CWinApp::GetProfile*() and CWinApp::WriteProfile*().
If one wants to use the registry more flexible, then one has to use the API-functions with their dozens of parameters. I don't know why MS doesn't provide a registry class in MFC - that would be quite easy ...
The CRegistry class I've developed allows one to use the registry in a simple way. In addition to the basic operations (loading and storing data), the class provides some more features. For instance one can walk the registry tree and perform some operations on any key/value-hit. Furthermore the class encapsulates differences between NT and Win95 (Aeh - you guessed that the Win32 API should be identical on both systems? Yes - the API is identical, but the performed action is not! Take a closer look at the description of the RegDeleteKey() function for instance.)
To handle all the different data types one can put into the registry,
the CRegistry class uses an information holder class CRegVal. If you have
to load a string from
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\DefaultUserName
you can do it as follows:
CString strKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon");
CRegistry reg(HKEY_LOCAL_MACHINE); // otherwise it defaults to HKEY_CURRENT_USER
CString strDefaultUserName;
CRegVal regval;
if( reg.LoadKey(strKey, TEXT("DefaultUserName"), regval) )
if( regval.GetValue(strDefaultUserName) )
// yep - got the name
Simple datatypes (numbers and strings) will be supported directly by the
CRegistry class, so you can write the sample above as follows:
CString strKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon");
CRegistry reg(HKEY_LOCAL_MACHINE); // otherwise it defaults to HKEY_CURRENT_USER
CString strDefaultUserName;
if( reg.LoadKey(strKey, TEXT("DefaultUserName"), strDefaultUserName) )
// yep - got the name
... but, if CRegistry::LoadKey() returns FALSE, this makes it harder to
check whether the type of the registry key is wrong or the entry does not
exist.
CRegistry doesn't support security (but that was no handicap for me
so far :-)
Changes in Revision 2
You can use Registry.cpp if you want to use the registry classes in a non-MFC application and RegMFC.cpp in an MFC-based application. RegMFC.cpp will support some more methods for use with MFC.For a build with MFC, you have to insert both files (Registry.cpp and RegMFC.cpp) into your project, but to exclude Registry.cpp from build.
In a non-MFC build you have to include Registry.cpp into your project only. In this case you don't need RegMFC.cpp.
Normally Registry.h detects whether you build an MFC version or not. If you want to build a non-MFC version in all circumstances, you can #define _REG_NO_MFC_BUILD.
Furthermore you can #define _REG_NO_TREEWALK to shrink the size of the resulting object files. This #define hides the CRegistry::RegistryTreeWalk() function and its associates. Use the _REG_NO_TREEWALK if you sure know, that you don't need the RegistryTreeWalk() method and want to reduce the code of your application/dll.
If you plan to use the CRegistry class in a non-MFC project you really should #define STRICT to make sure the class behaves correct in all circumstances. This is absolutly necessary, if you insert the class in a non-MFC dll that might be used in a MFC application.
CRegistry now is ready for use with UNICODE.
Changes in Revision 3
- The RegistryTreeWalk() method no longer reports a wrong "depth" to the methods OnValueHit() and OnKeyHit().
- The member USHORT m_usDepth was deleted
- eliminated a memory leak in DeleteKey() (thanks to Tobias Krueger)
- several bugfixes in DeleteKey() (sent in by Tobias Krueger)
Changes in Revision 4
- Some of the CRegVal::SetValue() methods changed. Most changes are for UNICODE applications (allocated too less memory). CRegVal::SetValue(const CStringArray &) is the only method that changes even for non-UNICODE applications. If you write CStringArrays to the registry, you really should upgrade to this revision!
Changes in Revision 5
- Bug fixed in the RegTreeWalk-function (thanks to Pieter E. Roos and Daniel G. Hyams): The RegEnumValue() function returns the number of bytes read in the last parameter. Since that value is stored in the CRegVal helper class, the next time RegVal was used to receive information from RegEnumValue(), RegEnumValue() thought that the buffer that it can put data in is smaller than it really is.
- The sample is now a VC 6 project (sorry to all of you, who have only older versions of VC - but I have to be up to date ...)
Usage
If you want to use the class in a MFC environment, you have to include all three files to your project, but to exclude Registry.cpp from build. To do so, right-click the file in the FileView of the workspace window and select Settings ... . Make sure you select All Configurations. Now select the General page and check the field Exclude file from build.In a pure Win32 project you will need Registry.[h|cpp] only.
CRegistry consists of three files:
Registry.h
Registry.cpp
RegMFC.cpp
Download Source 12 KB
Download Sample Project 28 KB
Date Last Updated: February 3, 1999

Comments
This class is not thread safe. Wait for Revision 6.
Posted by mmoore on 04/29/2009 02:15pmIn http://msdn.microsoft.com/en-us/library/ms724836(VS.85).aspx we find this: "The predefined handles are not thread safe. Closing a predefined handle in one thread affects any other threads that are using the handle." This means that it is not legitimate to call RegCloseKey on a predefined handle such as HKEY_LOCAL_MACHINE, but this class will do that if you create a class object with a predefined key. This causes intermittent failures of registry access in other threads of the same application. We are trying to notify the author of this problem and we are confident he will shortly provide revised code.
-
ReplyWork-around until Revision 6.
Posted by KevinSorensen on 04/29/2009 02:26pmIn the meantime we do the following before every RegCloseKey( hKey_p ) call: if (!IsPredefined( hKey_p )) RegCloseKey( hKey_p ); Where IsPredefined is the following: BOOL CRegistry::IsPredefined( HKEY hKey ) { return ((hKey == HKEY_CLASSES_ROOT) || (hKey == HKEY_CURRENT_CONFIG) || (hKey == HKEY_CURRENT_USER) || (hKey == HKEY_LOCAL_MACHINE) || (hKey == HKEY_PERFORMANCE_DATA) || (hKey == HKEY_PERFORMANCE_NLSTEXT) || (hKey == HKEY_PERFORMANCE_TEXT) || (hKey == HKEY_USERS)); }ReplyQuestion marks at end of retrieved strings
Posted by Bob H on 11/06/2006 12:02pmI am getting question marks at the end of retrieved strings. I believe it is only occurring when the build is unicode. Example: // value is set sValue = m_sPrevFontName; // value is "Arial" User.SaveKey(sKey, TEXT("PrevFontName"), sValue); // value is retrieved if (User.LoadKey(sKey, TEXT("PrevFontName"), sValue)) m_sPrevFontName = sValue; now sValue is "Arial???????"
ReplyWhy can't i get REG_DWORD (Numbers) data from the registry?
Posted by Legacy on 07/15/2002 12:00amOriginally posted by: Thorin
I can get strings from the registry but not numbers... any clues as to why?? Or is there any way i can convert CRegVal to an int?
ReplyGreat Job
Posted by Legacy on 05/24/2002 12:00amOriginally posted by: Douglas Brook
ReplyUnable to do RegTreeWalk Walkin
Posted by Legacy on 12/13/2001 12:00amOriginally posted by: Will'o the Wisp
Well im not able to get a Tree...
i.e.: Im Checking HKEY_CURRENT_USER
Software\\ANY
this key has 2 subkeys (any1 and any2)... i want to read
them out so that i can save them in a temp string to
call them later please help!
thanx!
ReplyCan I use CRegistry class in Windows CE?
Posted by Legacy on 12/28/2000 12:00amOriginally posted by: Rex Valderama
ReplyHow can i port this class in Windows CE environment? I was trying to include the files in a project and some Functions are not supported by WinCE.
Any help would be appreciated.
Resource not being freed.
Posted by Legacy on 09/29/2000 12:00amOriginally posted by: Sanjeev Kapoor
Replysample has some errors.
Posted by Legacy on 05/26/2000 12:00amOriginally posted by: kwon-myongjin
one error and two warnning.
in the registry.cpp
comfiler says.
i am a beginner.
ReplyUNICODE bug - buffer not properly terminated
Posted by Legacy on 03/24/2000 12:00amOriginally posted by: Armin Balke
Hi,
there is a problem with writing UNICODE strings.
If I use
CRegVal :: SetValue( LPCTSTR pszValue_p, BOOL bExpanded_p )
this line:
m_pbyteData[ dwSize ] = TEXT('\0') ;
does only set the byte one bevor the last byte. The last byte will stay undefined. As those kind of line occure multiple times in the code, it should be better to modify
BYTE * CRegVal :: AllocateDataBuffer( DWORD dwSize_p )
so that all byte in the buffer will be initially set to zero. Look at the code below:
BYTE * CRegVal :: AllocateDataBuffer( DWORD dwSize_p ) {
if( m_pbyteData )
HeapFree( m_hHeap, 0, m_pbyteData ) ;
m_pbyteData = (BYTE *) HeapAlloc( m_hHeap, HEAP_ZERO_MEMORY, dwSize_p ) ;
if( ! m_pbyteData ) {
TRACE0( "CRegVal::AllocateDataBuffer(): HeapAlloc() system call failed.\n" );
}
m_dwDataSize = dwSize_p ;
return m_pbyteData ;
}
ReplyI�m also interested in connections to a remote registry...
Posted by Legacy on 12/15/1999 12:00amOriginally posted by: Jaime
I can't get the way for connecting a remote registry, nor using the RegConnectRegistry() API function, neither using a wrapper class that i'm trying to implement. What is wrong in a call to the API functions that looks
RegConnectRegistry( _T( "\\\\MyMachine\\"), hParentKey, &hKey )
???
I would like somebody to help me, thank you
ReplyLoading, Please Wait ...