Add your own alternative version
Stats
161.9K views 2.4K downloads 63 bookmarked
Posted
30 Jun 2002
|
Comments and Discussions
|
|
|
Hello,
I think there is a bug if you want to use this class in Unicode projects. Line 497 should read
if (RegSetValueEx(m_hKey, m_key.c_str(), 0, REG_SZ, (BYTE *)m_value.c_str(), (DWORD)(m_value.size()+1)*sizeof(TCHAR))==ERROR_SUCCESS)<br />
The "sizeof(TCHAR)" is necessary if TCHAR is not 1 byte.
Am I correct?
|
|
|
|
|
As is, this class will only return the first null terminated string portion of a multi-string registry entry. I have modified the class so that the CRegString() method will automatically determine whether entry is regular string or multi-string and return it correctly. Multi-strings are returned as vertical bar or pipe-delimited strings (eg. "string-a|string-b"). Here is the code modification:
CString CRegString::read()
{
ASSERT(m_key != _T(""));
if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS)
{
int size = 0;
DWORD type;
RegQueryValueEx(m_hKey, m_key, NULL, &type, NULL, (LPDWORD) &size);
TCHAR* pStr = new TCHAR[size];
if(type==REG_MULTI_SZ)
{
delete [] pStr;
RegCloseKey(m_hKey);
TCHAR szResult[512] = _T("\0");
if(RegMultiRead(m_base, m_path.GetBuffer(), m_key.GetBuffer(),szResult,512)==0)
{
m_read=TRUE;
m_value = CString(szResult);
}
else
{
m_read=FALSE;
m_value = m_defaultvalue;
}
m_path.ReleaseBuffer();
m_key.ReleaseBuffer();
return m_value;
}
if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) pStr,(LPDWORD) &size)==ERROR_SUCCESS)
{
m_value = CString(pStr);
delete [] pStr;
ASSERT(type==REG_SZ);
m_read = TRUE;
RegCloseKey(m_hKey);
return m_value;
}
else
{
delete [] pStr;
RegCloseKey(m_hKey);
return m_defaultvalue;
}
}
return m_defaultvalue;
}
And then you must add the corresponding new method to the CRegString class:
DWORD CRegString::RegMultiRead(HKEY hHive, LPTSTR szKey, LPTSTR szValue, LPTSTR szResult, size_t iResultSize)
{
long lRet = 0;
HKEY hKey;
if (lRet = RegOpenKeyEx(hHive,szKey,0,KEY_EXECUTE,&hKey) == ERROR_SUCCESS)
{
DWORD dwType = 0;
DWORD dwSize = iResultSize;
DWORD dwCapacity = iResultSize;
LPTSTR szData = new TCHAR[iResultSize+4*sizeof(TCHAR)];
lRet = RegQueryValueEx(hKey,szValue,NULL,&dwType,(LPBYTE)szData,&dwSize);
if( (lRet != ERROR_SUCCESS) || (dwSize > dwCapacity) || dwType != REG_MULTI_SZ )
{
RegCloseKey(hHive);
delete[] szData;
return dwSize;
}
LPTSTR szToken = NULL;
LPTSTR szTmp = new TCHAR[dwCapacity];
_tcscpy (szTmp, _T("\0"));
szToken = szData;
while( szToken != NULL )
{
_tcscat (szTmp, szToken);
szToken = szToken + _tcslen (szToken) + sizeof(TCHAR);
if (_tcslen (szToken) > 0)
_tcscat (szTmp, _T("|"));
else
szToken = NULL;
}
_tcscpy(szResult, szTmp);
delete[] szData;
delete[] szTmp;
RegCloseKey(hKey);
RegCloseKey(hHive);
}
else
return lRet;
return 0;
}
In business, if two people always agree, one of them is unnecessary.
|
|
|
|
|
ok ive never used a tab control before i have no clue as to go about it. could someone give me a sample as to how to put a control on a tab all im going to use is check boxs and a few edits.
thanks in advance.
|
|
|
|
|
This is very useful. Very easy to use and powerful.
The only trouble I have with it is that if I try to read a non-existant key, it should either return null, or give an error indicating that there is no key. Returning the default value can be confusing as this is data that might then be mishandled.
Perhaps returning the default value on non-keys could be an option that could be turned on or off?
Anyway, this is very helpful.
Thanks!
|
|
|
|
|
Hi all!;)
I want to read and write to registry use unicode character but i don't know how to do . Who can help me?
Thanks a lot.
|
|
|
|
|
As I'm learning, nothing in life is certain, esp. so with Windows. This class, since it writes to something VERY important should be throwing exceptions. Might just add those and send to the author.
later....
C. Gilley
Will program for food...
Whoever said children were cheaper by the dozen... lied.
|
|
|
|
|
Just wanted you to know that it is excellent class.
Sincerely,
Alex Chirokov
|
|
|
|
|
Hello,
I'm using you little registry class library and I must say that it does the job almost perfect! I found a little "feature" which I don't know if it's there on purpose or as a surprise..
This "feature" is in the constructor / read method of the CRegBase derived classes. This is what happens:
I call the constructor with a default value. The registry value / key don't exist yet. The read function returns the default value. The variable m_value doesn't change! So after the constructor finished the object has an invalid default value. (Not the one I specified.)
The code now looks like this:
<br />
// constructor<br />
m_value = "";<br />
m_defaultvalue = def;<br />
m_force = force;<br />
m_base = base;<br />
m_read = FALSE;<br />
key.TrimLeft(_T("\\"));<br />
m_path = key.Left(key.ReverseFind(_T('\\')));<br />
m_path.TrimRight(_T("\\"));<br />
m_key = key.Right(key.GetLength() - key.ReverseFind(_T('\\')));<br />
m_key.Trim(_T("\\"));<br />
read();<br />
<br />
// read method<br />
ASSERT(m_key != _T(""));<br />
if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS)<br />
{ <br />
int size = 0;<br />
DWORD type;<br />
RegQueryValueEx(m_hKey, m_key, NULL, &type, NULL, (LPDWORD) &size);<br />
TCHAR* pStr = new TCHAR[size];<br />
if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) pStr,(LPDWORD) &size)==ERROR_SUCCESS)<br />
{<br />
m_value = CString(pStr);<br />
delete [] pStr;<br />
ASSERT(type==REG_SZ);<br />
m_read = TRUE;<br />
RegCloseKey(m_hKey);<br />
return m_value;<br />
} <br />
else<br />
{<br />
delete [] pStr;<br />
RegCloseKey(m_hKey);<br />
return m_defaultvalue;<br />
}<br />
}<br />
// Note: the variable m_value is not changed here!<br />
return m_defaultvalue;<br />
And I think that the code should look like this:
<br />
// constructor<br />
m_value = "";<br />
m_defaultvalue = def;<br />
m_force = force;<br />
m_base = base;<br />
m_read = FALSE;<br />
key.TrimLeft(_T("\\"));<br />
m_path = key.Left(key.ReverseFind(_T('\\')));<br />
m_path.TrimRight(_T("\\"));<br />
m_key = key.Right(key.GetLength() - key.ReverseFind(_T('\\')));<br />
m_key.Trim(_T("\\"));<br />
// Option 1, change this line to m_value = read()<br />
read();<br />
<br />
// read method<br />
ASSERT(m_key != _T(""));<br />
if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS)<br />
{ <br />
int size = 0;<br />
DWORD type;<br />
RegQueryValueEx(m_hKey, m_key, NULL, &type, NULL, (LPDWORD) &size);<br />
TCHAR* pStr = new TCHAR[size];<br />
if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) pStr,(LPDWORD) &size)==ERROR_SUCCESS)<br />
{<br />
m_value = CString(pStr);<br />
delete [] pStr;<br />
ASSERT(type==REG_SZ);<br />
m_read = TRUE;<br />
RegCloseKey(m_hKey);<br />
return m_value;<br />
} <br />
else<br />
{<br />
delete [] pStr;<br />
RegCloseKey(m_hKey);<br />
// Option 2 modify the function as follows<br />
// Note: no value returned here!<br />
}<br />
}<br />
// and modify this line<br />
return (m_value = m_defaultvalue);<br />
I think that option 2 is the better option, because that way m_value is always changed, which I thinkt is the purpose of the read() method.
Besides that, it's a great class!
I also got the blogging virus..[^]
|
|
|
|
|
and sure Trim is not a member of CString, then...
|
|
|
|
|
I think that maybe it's a bug.
I think that it maybe should like this:
m_key.TrimLeft(_T("\\"));
And i believe it is right with trimleft().
|
|
|
|
|
Trim is now a member of the old MFC CString class, but here is what google found:
"The trimChars can be either a string of the characters or an integer array of characters that will be trimmed from both ends"
so instead of
string.Trim()
i used
string.TrimLeft();
string.TrimRight();
so far it works,
Sincerely,
Alex Chirokov
|
|
|
|
|
Yes, Trim is a valid CString function... BUT.. it returns the result rather than changing the object directly. So the line MyString.trim() , while being valid code, will have no effect as the result is lost... It needs to be written CString szTrimmed = MyString.Trim() , and now the result of the Trim() operation is captured in the szTrimmed variable.
Trim operates on both ends of the string as opposed to TrimLeft and TrimRight which operate on only one end -- so if MyString = "*****Important String!!!!!!" , you could use szTrimmed = MyString.Trim("*!"); and the result would be "Important String".
The important point here is that the reason there is data loss in the example code, is because he didn't assign a variable to catch the returned result of the Trim operation.
In business, if two people always agree, one of them is unnecessary.
|
|
|
|
|
The .reg file saved by RegSaveKey() is a binary file.
How to export registry as an ASCII text file?
|
|
|
|
|
Hello,
No problem when I use removeValue(),
however; when I use removeKey() I get linker errors?
How do I fix the linker errors, or how can
I remove keys without using removeKey()?
Linking...
maindoc.obj : error LNK2001: unresolved external symbol __imp__SHDeleteKeyA@8
../../Apps/Debug/SPMNotify.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
VC++ 6.0 SP5
Thanks,
Jacques
|
|
|
|
|
Just add Shlwapi.lib import library to your VS 5 project (Project/Settings/Settings for all configurations/Link/Object/library modules).
|
|
|
|
|
thanks for posting this outstanding code!
|
|
|
|
|
Is there any way to use this registry class in program that does not support MFC?
I would like to use this registry class in an existing DLL that does not support MFC. I think it is rather difficult to make that DLL to support MFC, so I would like to see if there is any way to use this class with no support of MFC.
I am definitely open to the suggestion on how to change a DLL to support MFC with minimum effort.
Thanks,
LT
|
|
|
|
|
This is one heck of a class library!
keep up the great work!
|
|
|
|
|
Hi,
Do you know how to load an entire .reg file programmatically?
I didn't see that anywhere ?
Thanks.
|
|
|
|
|
Thought this little bit may be of use for some.
The class declares CRegStdWORD instead of CRegStdDWORD as you (and I) would expect. Those programs referencing CRegStdDWORD will not compile. Since I did not want to change a lot of the code, adding this line to the end of registry.h provides a quick fix:
typedef CRegStdWORD CRegStdDWORD;
Thanks for the great class!
|
|
|
|
|
This was exactly what I was looking for. thanks a lot for writing it.
|
|
|
|
|
Congratulations ; is just what I was looking for, thanks a lot.
People say that I am a perverse person, but are not truth because I have the heart of a boy.... I have it in a bottle with formol in my writing-desk.
|
|
|
|
|
Hi,
I am getting the following linker error:
error LNK2001: unresolved external symbol "public: class CRegStdWORD & __thiscall CRegStdWORD::operator=(unsigned long)" (??4CRegStdWORD@@QAEAAV0@K@Z)
Debug/StickyNotes.exe : fatal error LNK1120: 1 unresolved externals.
Looks like CRegStdWORD::operator=(DWORD d) is not defined.
Is it a bug or a feature? Or am I missing something?
With respect,
Igor.
|
|
|
|
|
Yes, I'm getting the same thing when trying to link to the CRegistry code, part of another DLL. Looks like it isn't exported for some reason. Help?
error LNK2001: unresolved external symbol "public: class CRegStdWORD & __thiscall CRegStdWORD::operator=(unsigned long)" (??4CRegStdWORD@@QAEAAV0@K@Z)
|
|
|
|
|
|
General News Suggestion Question Bug Answer Joke Praise Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
|