在前一篇中,我有提到应用程序关联的方法,归根结底就是在注册表中添加了相应的内容。但这样有个不好的地方,就是会在注册表中留下很多垃圾信息。怎样在调试完程序后,自动清除注册表中冗余的信息呢?我在这里提供一个简单的方法,与大家分享哈。
(一)跟大家介绍一个c++的注册表操作的封装类
1.注册表项RegEntry.h
- // CRegEntry: interface for the CRegEntry class.
- //
- //
- #if !defined(_REGENTRY_H_INCLUDED)
- #define _REGENTRY_H_INCLUDED
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- class CRegistry;
- class CRegEntry
- {
- public:
- CRegEntry(CRegistry* Owner = NULL);
- virtual ~CRegEntry() { if (lpszName) delete [] lpszName; if (lpszStr) delete [] lpszStr; };
- /* -----------------------------------------*
- * Operators *
- * -----------------------------------------*/
- CRegEntry& operator =( CRegEntry& cregValue );
- CRegEntry& operator =( LPCTSTR lpszValue );
- CRegEntry& operator =( LPDWORD lpdwValue );
- CRegEntry& operator =( DWORD dwValue ) { return (*this = &dwValue); }
- operator LPTSTR();
- operator DWORD();
- // Data types without implemented conversions
- // NOTE: I realize these will only check asserts
- // when a value is set and retrieved during the
- // same session. But it is better than no check.
- REGENTRY_NONCONV_STORAGETYPE(POINT);
- REGENTRY_NONCONV_STORAGETYPE(RECT);
- // Numeric types with conversions
- // If you'd like to add more, follow this form:
- // data type, max string length + 1, format specification, from string, from DWORD
- REGENTRY_CONV_NUMERIC_STORAGETYPE(__int64, 28, %I64d, _ttoi64(lpszStr), (__int64)dwDWORD)
- REGENTRY_CONV_NUMERIC_STORAGETYPE(double, 18, %f, _tcstod(lpszStr, NULL), (double)dwDWORD)
- REGENTRY_CONV_NUMERIC_STORAGETYPE(bool, 2, %d, (_ttoi(lpszStr) != 0), (dwDWORD != 0))
- REGENTRY_CONV_NUMERIC_STORAGETYPE(int, 12, %d, _ttoi(lpszStr), (int)dwDWORD)
- REGENTRY_CONV_NUMERIC_STORAGETYPE(UINT, 11, %d, (UINT)_tcstoul(lpszStr, NULL, NULL), (UINT)dwDWORD)
- // Types with conversions: type to/from string, type from unsigned long
- REGENTRY_CONV_STORAGETYPE(tstring, _R_BUF(_MAX_REG_VALUE); _tcscpy(buffer, Value.c_str());,
- lpszStr, _ultot(dwDWORD, lpszStr, NULL), _T(""))
- /* -----------------------------------------*
- * Member Variables and Functions *
- * -----------------------------------------*/
- LPTSTR lpszName; // The value name
- UINT iType; // Value data type
- void InitData(CRegistry* Owner = NULL);
- void ForceStr();
- bool Delete();
- /* The following six functions handle REG_MULTI_SZ support: */
- void SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal = false);
- void MultiRemoveAt(size_t nIndex);
- void MultiSetAt(size_t nIndex, LPCTSTR lpszVal);
- LPTSTR GetMulti(LPTSTR lpszDest, size_t nMax = _MAX_REG_VALUE);
- LPCTSTR MultiGetAt(size_t nIndex);
- size_t MultiLength(bool bInternal = false);
- size_t MultiCount();
- void SetBinary(LPBYTE lpbValue, size_t nLen);
- void GetBinary(LPBYTE lpbDest, size_t nMaxLen);
- size_t GetBinaryLength();
- bool Convertible() { return __bConvertable; }
- __inline SetOwner(CRegistry* Owner) { __cregOwner = Owner; }
- template <class T>void SetStruct(T &type) { SetBinary((LPBYTE) &type, sizeof(T)); }
- template <class T>void GetStruct(T &type) { GetBinary((LPBYTE) &type, sizeof(T)); }
- __inline IsString() { return (iType == REG_SZ); }
- __inline IsDWORD() { return (iType == REG_DWORD); }
- __inline IsBinary() { return (iType == REG_BINARY); }
- __inline IsMultiString() { return (iType == REG_MULTI_SZ); }
- __inline IsStored() { return __bStored; }
- __inline Exists() { return __bStored; }
- __inline MultiClear() { SetMulti(_T("/0"), 2); }
- __inline MultiAdd(LPCTSTR lpszVal) { MultiSetAt(MultiCount(), lpszVal); }
- protected:
- CRegistry* __cregOwner;
- bool __bConvertable;
- bool __bStored;
- private:
- /* Create a variable for each prominent data type */
- DWORD dwDWORD;
- LPTSTR lpszStr;
- std::vector<BYTE> vBytes;
- std::vector<tstring> vMultiString;
- };
- #endif
2.注册表节点Registry.h
- #if !defined(_REGISTRY_H_INCLUDED)
- #define _REGISTRY_H_INCLUDED
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- /* Silence STL warnings */
- #pragma warning (disable : 4786)
- #pragma warning (disable : 4514)
- #pragma warning (push, 3)
- #ifdef _UNICODE
- #if !defined(UNICODE)
- #define UNICODE
- #endif
- #endif
- #include <windows.h>
- #include <math.h>
- #include <TCHAR.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <vector>
- #include <assert.h>
- /* ====================================
- * Begin Preprocessor Definitions
- *
- * - Ugly, but well worth it.
- * ==================================== */
- #ifdef _UNICODE
- typedef std::wstring tstring;
- #else
- typedef std::string tstring;
- #endif
- /* CRegistry Open Flags */
- #define CREG_CREATE 1
- #define CREG_AUTOOPEN 2
- #define CREG_NOCACHE 4
- /* CRegistry Behaivor flags */
- #define CREG_LOADING 8
- #define _MAX_REG_VALUE 2048 // Maximum Value length, this may be increased
- #define NOT_ES(func) func != ERROR_SUCCESS
- #define IS_ES(func) func == ERROR_SUCCESS
- #define _R_BUF(size) _TCHAR buffer[size]
- #define REGENTRY_AUTO __cregOwner->GetFlags() & CREG_AUTOOPEN
- #define REGENTRY_TRYCLOSE if (REGENTRY_AUTO) __cregOwner->AutoClose()
- #define REGENTRY_SZ_SAFE iType == REG_SZ || iType == REG_BINARY
- #define REGENTRY_ALLOWCONV(b) __bConvertable = b;
- #define REGENTRY_REFRESH_IF_NOCACHE /
- if (__cregOwner->GetFlags() & CREG_NOCACHE && /
- REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_QUERY_VALUE ))/
- __cregOwner->Refresh();
- #define REGENTRY_UPDATE_MULTISTRING /
- LPTSTR lpszBuffer = new _TCHAR[_MAX_REG_VALUE]; /
- REGENTRY_SETLOADING(+); GetMulti(lpszBuffer); REGENTRY_SETLOADING(-); /
- SetMulti(lpszBuffer, MultiLength(true), true); /
- delete [] lpszBuffer;
- #define REGENTRY_KEYVALID(auto_access) /
- lpszName && ((REGENTRY_AUTO && __cregOwner->AutoOpen(auto_access)) || (!(REGENTRY_AUTO) && __cregOwner->hKey != NULL))
- #define REGENTRY_NOTLOADING /
- !(__cregOwner->GetFlags() & CREG_LOADING)
- #define REGENTRY_SETLOADING(op) /
- __cregOwner->__dwFlags op= CREG_LOADING
- #define REGENTRY_BINARYTOSTRING /
- if (iType == REG_BINARY) { ForceStr(); lpszStr = *this; }
- #define REGENTRY_NONCONV_STORAGETYPE(type) /
- CRegEntry& operator=( type &Value ){ REGENTRY_ALLOWCONV(false) SetStruct(Value); return *this; } /
- operator type(){ type Return; GetStruct(Return); return Return; }
- #define REGENTRY_CONV_STORAGETYPE(type, to_sz, from_sz, from_dw, no_result) /
- CRegEntry& operator=( type Value ) { to_sz return (*this = (LPCTSTR)(buffer)); } /
- operator type(){ REGENTRY_BINARYTOSTRING return (REGENTRY_SZ_SAFE ? from_sz :(iType == REG_DWORD ? from_dw : no_result)); }
- #define REGENTRY_CONV_NUMERIC_STORAGETYPE(type, maxlen, form, from_sz, from_dw) /
- REGENTRY_CONV_STORAGETYPE(type, _R_BUF(maxlen); _stprintf(buffer, _T(#form), Value);, from_sz, from_dw, 0)
- /* ====================================
- * Include CRegEntry Class Definition
- * ==================================== */
- #include "RegEntry.h"
- /* ====================================
- * Begin CRegistry Class Definition
- * ==================================== */
- using namespace std;
- class CRegistry {
- public:
- CRegistry (DWORD flags = CREG_CREATE);
- virtual ~CRegistry() { Close(); for (int i=0; i < _reEntries.size(); ++i) delete _reEntries[i]; delete [] _lpszSubKey; }
- CRegEntry& operator[](LPCTSTR lpszVName);
- CRegEntry* GetAt(size_t n) { assert(n < Count()); return _reEntries.at(n); }
- bool Open(LPCTSTR lpszRegPath, HKEY hRootKey = HKEY_LOCAL_MACHINE,
- DWORD dwAccess = KEY_QUERY_VALUE | KEY_SET_VALUE, bool bAuto = false);
- bool AutoOpen(DWORD dwAccess);
- void AutoClose();
- void Close();
- bool Refresh();
- static bool KeyExists(LPCTSTR lpszRegPath, HKEY hRootKey = HKEY_LOCAL_MACHINE);
- bool SubKeyExists(LPCTSTR lpszSub);
- void DeleteKey();
- __inline GetFlags() { return __dwFlags; }
- __inline Count() { return _reEntries.size(); }
- HKEY hKey; /* Registry key handle */
- protected:
- DWORD __dwFlags;
- friend void CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal);
- friend void CRegEntry::MultiRemoveAt(size_t nIndex);
- private:
- void InitData();
- void DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey);
- HKEY _hRootKey;
- LPTSTR _lpszSubKey;
- std::vector<CRegEntry *> _reEntries;
- };
- #pragma warning(pop)
- #endif
3.Registry.cpp
- /*// --- FILE INFORMATION -----------------------------
- CRegistry.cpp
- Classes: CRegEntry and CRegistry
- Author: Stuart Konen
- Email: skonen@gmail.com
- Date: 12/1/2004 (MM/DD/YYYY)
- Version: 1.00
- (-!-) If you're going to use these classes please do not
- remove these comments... To use these classes, simply #include
- Registry.h . In MFC you should also turn off precompiled headers
- for this file, in VC++ this can be done by navigating to:
- Project->Settings->Project Name->CRegistry.cpp->C/C++->Precompiled Headers
- *///----------------------------------------------------
- #include "stdafx.h"
- #include "Registry.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #pragma warning (disable : 4706)
- /* ===================================================
- * CONSTRUCTOR
- * =================================================*/
- CRegEntry::CRegEntry(CRegistry *Owner) {
- assert(Owner);
- InitData(Owner);
- }
- /* ===================================================
- * CRegEntry::InitData(CRegistry *Owner)
- *
- * Initializes the entries default values and sets the entries
- * owner (CRegistry). This is only called during construction.
- */
- void CRegEntry::InitData(CRegistry *Owner) {
- dwDWORD = iType = 0;
- lpszName = lpszStr = NULL;
- __bStored = false;
- __bConvertable = true;
- __cregOwner = Owner;
- }
- /* ===================================================
- * CRegEntry::ForceStr()
- *
- * Forces the memory allocation for the entry's string value, if it
- * has not already been allocated.
- */
- void CRegEntry::ForceStr() {
- if (lpszStr == NULL) { lpszStr = new _TCHAR[_MAX_REG_VALUE]; lpszStr[0] = 0; }
- }
- /* ===================================================
- * CRegEntry::operator=(LPCTSTR lpszValue)
- *
- * OPERATOR: Assigns a const character array to the open
- * registry value. The registry value type will be REG_SZ.
- */
- CRegEntry& CRegEntry::operator=(LPCTSTR lpszValue) {
- size_t nValueLen = (_tcslen(lpszValue) + 1)*sizeof(TCHAR);
- assert(nValueLen <= _MAX_REG_VALUE);
- ForceStr(); iType = REG_SZ;
- _tcsncpy(lpszStr, lpszValue, nValueLen > _MAX_REG_VALUE ? _MAX_REG_VALUE : nValueLen);
- REGENTRY_ALLOWCONV(true)
- if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_SET_VALUE ))
- RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_SZ, (LPBYTE)lpszValue, nValueLen);
- REGENTRY_TRYCLOSE;
- __bStored = true;
- return *this;
- }
- /* ===================================================
- * CRegEntry::operator=(LPDWORD lpdwValue)
- *
- * OPERATOR: Assigns a DWORD to the open registry value.
- * The registry value type will be REG_DWORD.
- */
- CRegEntry& CRegEntry::operator=(LPDWORD lpdwValue) {
- iType = REG_DWORD;
- memcpy(&dwDWORD, lpdwValue, sizeof( DWORD ));
- REGENTRY_ALLOWCONV(true)
- if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_SET_VALUE ))
- RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_DWORD, (LPBYTE)&dwDWORD, sizeof( DWORD ));
- REGENTRY_TRYCLOSE;
- __bStored = true;
- return *this;
- }
- /* ===================================================
- * CRegEntry::operator=(CRegEntry& cregValue)
- *
- * OPERATOR: Copys value information from the specified
- * registry entry (CRegEntry) into this entry.
- */
- CRegEntry& CRegEntry::operator=(CRegEntry& cregValue) {
- if (this == &cregValue)
- return *this;
- if (lpszName == NULL) {
- size_t nNameLen = _tcslen(cregValue.lpszName) + 1;
- lpszName = new _TCHAR[nNameLen]; _tcsncpy(lpszName, cregValue.lpszName, nNameLen);
- }
- switch ((iType = cregValue.iType)) {
- case REG_SZ:
- return (*this = (ForceStr(), cregValue.lpszStr));
- break;
- case REG_MULTI_SZ: {
- LPTSTR lpszBuf = new _TCHAR[_MAX_REG_VALUE];
- SetMulti(cregValue.GetMulti(lpszBuf), cregValue.MultiLength());
- delete [] lpszBuf; return *this;
- }
- break;
- case REG_BINARY: {
- size_t n = cregValue.vBytes.size(); LPBYTE buf = new BYTE[n];
- cregValue.GetBinary(buf, n); SetBinary(buf, n);
- delete [] buf; return *this;
- }
- break;
- default:
- return (*this = cregValue.dwDWORD);
- }
- }
- /* ===================================================
- * CRegEntry::operator LPTSTR()
- *
- * OPERATOR: Converts (if required) and returns the open registry
- * value as a null terminated string.
- */
- CRegEntry::operator LPTSTR() {
- /* If caching is disabled, refresh the entries */
- REGENTRY_REFRESH_IF_NOCACHE
- assert(__bConvertable); // Check for conversion implementation
- ForceStr();
- switch (iType) {
- case REG_DWORD:
- _stprintf(lpszStr, _T("%lu"), dwDWORD);
- break;
- case REG_MULTI_SZ:
- GetMulti(lpszStr);
- break;
- case REG_BINARY: {
- _tcsncpy(lpszStr, (const _TCHAR*)&vBytes[0], vBytes.size());
- lpszStr[vBytes.size()] = 0;
- }
- break;
- }
- return lpszStr;
- }
- /* ===================================================
- * CRegEntry::operator DWORD()
- *
- * OPERATOR: Converts (if required) and returns the open registry
- * value as an unsigned 32-bit integer (unsigned long).
- */
- CRegEntry::operator DWORD() {
- /* If caching is disabled, refresh the entries */
- REGENTRY_REFRESH_IF_NOCACHE
- assert(__bConvertable); // Check for conversion implementation
- REGENTRY_BINARYTOSTRING
- return (REGENTRY_SZ_SAFE ? _tcstoul(lpszStr, NULL, NULL) : dwDWORD);
- }
- /* ===================================================
- * CRegEntry::GetBinary(LPBYTE lpbValue, size_t nLen)
- *
- * Sets the registry value to a binary value (REG_BINARY)
- *
- * Important Params:
- *
- * LPBYTE lpbDest: Pointer to the byte array to store *
- * size_t nLen: Elements contained within the byte array.
- */
- void CRegEntry::SetBinary(LPBYTE lpbValue, size_t nLen) {
- if (!nLen) { assert(nLen); return; }
- iType = REG_BINARY;
- if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID ( KEY_SET_VALUE ) )
- RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_BINARY, lpbValue, nLen);
- REGENTRY_TRYCLOSE;
- __bStored = true;
- if (vBytes.size() < nLen) vBytes.reserve(nLen);
- vBytes.clear();
- do { vBytes.push_back(lpbValue[vBytes.size()]); }
- while (vBytes.size() < nLen);
- }
- /* ===================================================
- * CRegEntry::GetBinary(LPBYTE lpbDest, size_t nMaxLen)
- *
- * Gets the binary value of a value stored as REG_BINARY
- *
- * Important Params:
- *
- * LPBYTE lpbDest: Pointer to the byte array to fill
- * size_t nMaxLen: The maximum bytes to copy to lpbDest
- *
- * Notes: This will only work for values that were saved
- * using the binary registry type specification (REG_BINARY)
- */
- void CRegEntry::GetBinary(LPBYTE lpbDest, size_t nMaxLen) {
- assert(IsBinary()); // Must be stored as Binary
- REGENTRY_REFRESH_IF_NOCACHE
- if ((size_t)(&vBytes.back() - &vBytes.at(0)+1) == vBytes.size()*sizeof(BYTE))
- memcpy(lpbDest, (LPBYTE)&vBytes.at(0), vBytes.size() > nMaxLen ? nMaxLen : vBytes.size());
- else
- for (size_t n=0; n < vBytes.size() && n < nMaxLen; n++)
- lpbDest[n] = vBytes[n];
- }
- /* ===================================================
- * CRegEntry::GetBinaryLength()
- *
- * Returns the size of the binary value in bytes.
- */
- size_t CRegEntry::GetBinaryLength() {
- assert(IsBinary());
- REGENTRY_REFRESH_IF_NOCACHE
- return vBytes.size();
- }
- /* ===================================================
- * CRegEntry::SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal)
- *
- * Stores an array of null-terminated string, terminated by two null characters.
- * For Example: First String/0Second/Third/0/0
- *
- * Important Params:
- *
- * LPCTSTR lpszValue: The string consisting of the null-terminated string array
- * size_t nLen: The number of characters in the string, including null characters
- *
- * Note: For inserting individual null-terminated strings into the array,
- * use MultiAdd or MultiSetAt.
- */
- void CRegEntry::SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal) {
- size_t nCur = 0, nPrev = 0, nShortLen = nLen;
- /* When this is internal, there is no need to repopulate the vector. */
- if (bInternal) goto SkipNoInternal;
- iType = REG_MULTI_SZ; vMultiString.clear();
- if (nLen <= 2) goto SkipNoInternal; // The string is empty : /0/0
- if (*(lpszValue + nShortLen-1) == '/0')
- nShortLen--;
- /* Populate a vector with each string part for easy and quick access */
- while ((nCur = (int)(_tcschr(lpszValue+nPrev, '/0')-lpszValue)) < nShortLen) {
- vMultiString.push_back(lpszValue+nPrev);
- nPrev = nCur+1;
- }
- SkipNoInternal:
- if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID ( KEY_SET_VALUE ) )
- RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_MULTI_SZ, (LPBYTE)lpszValue, nLen*sizeof(TCHAR));
- REGENTRY_TRYCLOSE;
- __bStored = true;
- }
- /* ===================================================
- * CRegEntry::MultiLength(bool bInternal = false)
- *
- * Returns the number of characters (including null) stored
- * in the full string. Don't confuse this with MultiCount()
- * which returns the number of strings stored in the array.
- */
- size_t CRegEntry::MultiLength(bool bInternal /*false*/) {
- //Ensure correct values with no cache
- if (!bInternal) REGENTRY_REFRESH_IF_NOCACHE
- for (size_t nLen = 0, nIndex = 0; nIndex < vMultiString.size(); nIndex++)
- nLen += vMultiString[nIndex].length() + 1;
- return nLen ? nLen+1 : 0;
- }
- /* ===================================================
- * CRegEntry::MultiCount()
- *
- * Returns the number of strings located within the array.
- */
- size_t CRegEntry::MultiCount() {
- // Ensure correct values with no cache
- REGENTRY_REFRESH_IF_NOCACHE
- return vMultiString.size();
- }
- /* ===================================================
- * CRegEntry::MultiRemoveAt(size_t nIndex)
- *
- * Simply removes the string stored at the zero-based index of nIndex
- */
- void CRegEntry::MultiRemoveAt(size_t nIndex) {
- // Ensure correct values with no cache
- REGENTRY_REFRESH_IF_NOCACHE
- assert(nIndex < vMultiString.size());
- vMultiString.erase(vMultiString.begin()+nIndex);
- // Update the registry
- REGENTRY_UPDATE_MULTISTRING
- }
- /* ===================================================
- * CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal)
- *
- * Alters the value of a string in the array located at
- * the 0 based index of nIndex. The new value is lpszVal.
- * The index must be within the bounds of the array, with
- * the exception of being == the number of elements in
- * which case calling this function is equal to calling
- * MultiAdd.
- */
- void CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal) {
- // Ensure correct values with no cache
- REGENTRY_REFRESH_IF_NOCACHE
- assert(nIndex <= vMultiString.size());
- iType = REG_MULTI_SZ;
- // Add a new string element if == elements+1
- if (nIndex == vMultiString.size())
- vMultiString.push_back(lpszVal);
- else
- vMultiString[nIndex] = lpszVal;
- // Update the registry
- REGENTRY_UPDATE_MULTISTRING
- }
- /* ===================================================
- * CRegEntry::MultiGetAt(size_t nIndex)
- *
- * Returns a constant pointer to the string located in
- * the array at the zero-based index of nIndex. Note that
- * the return value is not an STL string.
- */
- LPCTSTR CRegEntry::MultiGetAt(size_t nIndex) {
- // Ensure correct values with no cache
- REGENTRY_REFRESH_IF_NOCACHE
- assert(nIndex < vMultiString.size() && IsMultiString());
- return vMultiString[nIndex].c_str();
- }
- /* ===================================================
- * CRegEntry::GetMulti(LPCTSTR lpszDest, size_t nMax)
- *
- * Copys the entire null-terminated array string to lpszDest.
- * For Example: First String/0Second/Third/0/0
- *
- * Important Params:
- *
- * LPCTSTR lpszDest: Pointer to the character array to fill.
- * size_t nMax: The maximum characters to read, including null-characters
- *
- * Note: By default nMax is set to _MAX_REG_VALUE, you can retrieve
- * the length of the entire string by calling MultiLength().
- */
- LPTSTR CRegEntry::GetMulti(LPTSTR lpszDest, size_t nMax) {
- LPCTSTR strBuf;
- size_t nCur = 0, nLen = 0;
- assert(IsMultiString());
- if (!IsMultiString()) return &(lpszDest[0] = 0);
- /* If caching is disabled, refresh the entries */
- REGENTRY_REFRESH_IF_NOCACHE
- for (size_t n=0; n < vMultiString.size() && nCur < nMax; n++) {
- strBuf = vMultiString[n].c_str();
- nLen = vMultiString[n].length()+1;
- _tcsncpy(lpszDest + nCur, strBuf, (nLen >= nMax ? (nMax-nCur) : nLen) * sizeof(_TCHAR));
- nCur += nLen;
- }
- /* Add the final null termination */
- *(lpszDest + nCur) = 0;
- return lpszDest;
- }
- /* ===================================================
- * CRegEntry::Delete()
- *
- * Removes the value from the open registry key, returns
- * true on success and false on failure.
- */
- bool CRegEntry::Delete() {
- __bStored = false;
- if (REGENTRY_KEYVALID (KEY_SET_VALUE) )
- return (__cregOwner->AutoClose(), IS_ES(RegDeleteValue(__cregOwner->hKey, lpszName)));
- return false;
- }
- // BEGIN CREGISTRY FUNCTIONS
- /* ===================================================
- * CRegistry CONSTRUCTOR
- *
- * Flags:
- *
- * CREG_CREATE (default) - When attempting to open a key that
- * does not exist, create it.
- *
- * CREG_AUTOOPEN - Close the open registry key handle
- * after an action has been performed with it. Opens the
- * key whenever another action needs to be performed.
- *
- * ===================================================*/
- CRegistry::CRegistry(DWORD flags) {
- InitData(); __dwFlags = flags;
- }
- /* ===================================================
- * CRegistry::InitData()
- * Initializes the variables related to key locations to NULL.
- */
- void CRegistry::InitData() {
- _lpszSubKey = NULL;
- _hRootKey = hKey = NULL;
- }
- /* ===================================================
- * CRegistry::operator []( LPCTSTR lpszVName)
- *
- * OPERATOR: This will return the Registry Entry (CRegEntry) associated
- * with the given value name. If the value name does not exist in
- * the open key, it will be created.
- *
- * Note: If the value name is created, it is only stored in the actual
- * registry when the entry's value has been set.
- */
- CRegEntry& CRegistry::operator []( LPCTSTR lpszVName) {
- size_t nValueNameLen = _tcslen(lpszVName) + 1;
- assert(nValueNameLen <= _MAX_REG_VALUE);
- for (int i = _reEntries.size()-1; i >=0; i--) {
- if (!_tcsicmp(lpszVName, _reEntries[i]->lpszName))
- return *_reEntries[i];
- }
- /* Entry not found */
- _reEntries.push_back(new CRegEntry(this));
- _reEntries.back()->lpszName = new _TCHAR[nValueNameLen];
- _tcsncpy(_reEntries.back()->lpszName, lpszVName, (nValueNameLen > _MAX_REG_VALUE ? _MAX_REG_VALUE : nValueNameLen));
- return *_reEntries.back();
- }
- /* ===================================================
- * CRegistry::KeyExists()
- *
- * Returns true if the key exists and returns false if the key
- * does not exist or could not be opened. This may be called
- * as a static function.
- *
- * Example:
- * CRegistry::KeyExists("Software//Something", HKEY_LOCAL_MACHINE);
- */
- bool CRegistry::KeyExists(LPCTSTR lpszRegPath, HKEY hRootKey) {
- CRegistry cregTemp( NULL );
- return cregTemp.Open(lpszRegPath, hRootKey, KEY_QUERY_VALUE, true);
- }
- /* ===================================================
- * CRegistry::SubKeyExists()
- *
- * Returns true if the subkey exists within the currently
- * open key and false if not.
- */
- bool CRegistry::SubKeyExists(LPCTSTR lpszSub) {
- bool bResult;
- HKEY hTemp;
- if ((__dwFlags & CREG_AUTOOPEN && !AutoOpen(KEY_QUERY_VALUE)) || hKey == NULL) {
- assert(hKey);
- return false;
- }
- bResult = (RegOpenKeyEx(hKey, lpszSub, 0, KEY_QUERY_VALUE, &hTemp) == ERROR_SUCCESS);
- if (bResult) RegCloseKey(hTemp);
- if (__dwFlags & CREG_AUTOOPEN) AutoClose();
- return bResult;
- }
- /* ===================================================
- * CRegistry::Open(LPCTSTR lpszRegPath, HKEY hRootKey, bool bAuto)
- *
- * Opens the key in which values will be read and stored, if the key
- * is not already existent in the registry, it will be created (if the
- * CREG_CREATE) flag is present while constructing the class.
- *
- * Upon opening the registry key, all of the REG_DWORD and REG_SZ values
- * are loaded into a new corresponding CRegEntry for future access.
- *
- * Important Params:
- *
- * LPCTSTR lpszRegPath - A NULL terminated const character array containing,
- * the location of the subkey.
- * For example: "SOFTWARE//Microsoft//Windows//CurrentVersion//Run"
- *
- * HKEY hRootKey - An open key handle to the root key. By default
- * this value is set as HKEY_LOCAL_MACHINE.
- * Another Example: HKEY_CURRENT_USER
- *
- * Returns true on success and false on failure.
- */
- bool CRegistry::Open(LPCTSTR lpszRegPath, HKEY hRootKey, DWORD dwAccess, bool bAuto) {
- bool bNew = true;
- /* If the key is being auto opened, skip directly to opening */
- if (bAuto) goto SkipNoAuto;
- /* The key is being opened manually, if the key location differs
- from the last opened location, clear the current entries and
- store the path information for future auto opening and key
- deletion using DeleteKey() */
- if (_lpszSubKey){
- if (_tcsicmp(lpszRegPath, _lpszSubKey)) {
- /* If new key, clear any currently stored entries */
- for (size_t n=0; n<_reEntries.size(); n++)
- delete _reEntries[n];
- _reEntries.clear();
- delete [] _lpszSubKey;
- } else bNew = false;
- }
- if (bNew) {
- /* Store path information for auto opening */
- _lpszSubKey = new _TCHAR[_tcslen(lpszRegPath)+1];
- _tcscpy(_lpszSubKey, lpszRegPath);
- }
- _hRootKey = hRootKey;
- SkipNoAuto:
- /* This is where the key is actually opened (if all goes well).
- If the key does not exist and the CREG_CREATE flag is present,
- it will be created... Any currently opened key will be closed
- before opening another one. After opening the key, Refresh() is
- called and the key's values are stored in memory for future use. */
- if (hKey != NULL) Close();
- /* If auto opening is set and this is a manual opening
- set the appropriate access rights */
- if (__dwFlags & CREG_AUTOOPEN && !bAuto) {
- dwAccess = CREG_CREATE ? KEY_CREATE_SUB_KEY | KEY_QUERY_VALUE : KEY_QUERY_VALUE;
- }
- /* When key creation is enabled and auto opening is disabled,
- include key creation in the access rights */
- else if (__dwFlags & ~CREG_AUTOOPEN && __dwFlags & CREG_CREATE)
- dwAccess |= KEY_CREATE_SUB_KEY;
- /* Open or create the sub key, and return the result: */
- LONG lResult = (__dwFlags & CREG_CREATE ?
- RegCreateKeyEx(hRootKey, lpszRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, &hKey, NULL)
- : RegOpenKeyEx(hRootKey, lpszRegPath, 0, dwAccess, &hKey));
- return (lResult == ERROR_SUCCESS ? (bAuto ? true : Refresh()) : false);
- }
- /* ===================================================
- * CRegistry::AutoOpen()
- *
- * If the CREG_AUTOOPEN flag is true, this function is called whenever
- * an action needs to be performed involving the registry key.
- *
- * DWORD dwAccess controls the access required for key use.
- */
- bool CRegistry::AutoOpen(DWORD dwAccess) {
- assert(_lpszSubKey != NULL);
- return (hKey == NULL && __dwFlags & CREG_AUTOOPEN ? Open(_lpszSubKey, _hRootKey, dwAccess, true) : true);
- }
- /* ===================================================
- * CRegistry::AutoClose()
- *
- * If the CREG_AUTOOPEN flag is true, this function is called whenever
- * an action has been performed on an open registry key and the key is no longer
- * being accessed.
- */
- void CRegistry::AutoClose() {
- if (__dwFlags & CREG_AUTOOPEN) Close();
- }
- /* ===================================================
- * CRegistry::Refresh()
- *
- * Enumerates all the REG_SZ, REG_BINARY and REG_DWORD values within the open
- * registry key and stores them in a CRegEntry class for future
- * access. Returns true on success and false on failure.
- */
- bool CRegistry::Refresh() {
- DWORD dwBufferSize;
- DWORD dwType;
- DWORD dwNameLen;
- DWORD dwValueCount;
- LPBYTE lpbBuffer;
- DWORD dwPrevFlags = __dwFlags;
- _TCHAR cValueName[_MAX_PATH];
- if ((__dwFlags & CREG_AUTOOPEN && !AutoOpen(KEY_QUERY_VALUE)) || hKey == NULL)
- return false;
- if (NOT_ES(RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL)))
- return false;
- lpbBuffer = new BYTE[_MAX_REG_VALUE];
- /* Halt auto opening and set loading flag */
- __dwFlags = (__dwFlags | CREG_LOADING) & ~CREG_AUTOOPEN;
- if (dwValueCount > _reEntries.size())
- _reEntries.reserve(dwValueCount);
- for( DWORD dwIndex = 0; dwIndex < dwValueCount; dwIndex++) {
- dwNameLen = sizeof(cValueName); dwBufferSize = _MAX_REG_VALUE;
- cValueName[0] = 0;
- if (NOT_ES(RegEnumValue(hKey, dwIndex, cValueName, &dwNameLen, NULL, &dwType, lpbBuffer, &dwBufferSize)))
- continue;
- switch (dwType) {
- case REG_DWORD:
- this[0][cValueName] = (LPDWORD)lpbBuffer;
- break;
- case REG_SZ:
- this[0][cValueName] = (LPCTSTR)lpbBuffer;
- break;
- case REG_MULTI_SZ:
- this[0][cValueName].SetMulti((LPCTSTR)lpbBuffer, dwBufferSize/sizeof(TCHAR));
- break;
- case REG_BINARY:
- this[0][cValueName].SetBinary(lpbBuffer, (size_t)dwBufferSize);
- break;
- }
- }
- if ((__dwFlags = dwPrevFlags) & CREG_AUTOOPEN) AutoClose();
- delete [] lpbBuffer;
- return true;
- }
- /* ===================================================
- * CRegistry::DeleteKey()
- *
- * Deletes the key which is currently opened, including any
- * subkeys and values it may contain.
- *
- * NOTE: Use extreme caution when calling this function
- */
- void CRegistry::DeleteKey() {
- OSVERSIONINFO osvi;
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx(&osvi) && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
- DeleteKey(_hRootKey, _lpszSubKey);
- else
- RegDeleteKey(_hRootKey, _lpszSubKey);
- Close();
- }
- /* ===================================================
- * CRegistry::DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey)
- *
- * Private member function which is called by DeleteKey()
- * This function is designed for NT based systems as it recursively
- * deletes any subkeys present.
- */
- void CRegistry::DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey) {
- DWORD dwKeyLen;
- FILETIME ftTemp;
- HKEY hTempKey;
- LONG lResult = ERROR_SUCCESS;
- LPTSTR lpszKey = new _TCHAR[_MAX_PATH];
- if (!_tcslen(lpszSubKey) || !hPrimaryKey) { assert(hPrimaryKey != NULL); goto cleanup; }
- if (IS_ES(RegOpenKeyEx(hPrimaryKey, lpszSubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_WRITE, &hTempKey))){
- while (IS_ES(lResult)) {
- dwKeyLen = _MAX_PATH;
- lResult = RegEnumKeyEx(hTempKey, 0, lpszKey, &dwKeyLen, NULL, NULL, NULL, &ftTemp);
- if (lResult == ERROR_SUCCESS) DeleteKey(hTempKey, lpszKey);
- else if (lResult == ERROR_NO_MORE_ITEMS) RegDeleteKey(hPrimaryKey, lpszSubKey);
- }
- RegCloseKey(hTempKey); hTempKey = NULL;
- }
- cleanup: delete [] lpszKey;
- }
- /* ===================================================
- * CRegistry::Close()
- *
- * If a key is currently open, it will be closed. This should
- * be called when you no longer need to access the registry key
- * and the CREG_AUTOOPEN flag is not true. However, Close() is
- * called on class deconstruction so it is not required.
- */
- void CRegistry::Close() {
- if (hKey != NULL) {
- RegCloseKey(hKey); hKey = NULL;
- }
- }
(二)具体实施方案
1.把以上的三个文件加入到你的工程中去;
2.在MainFrm.cpp中包含相关的头文件
#include "Registry.h"
#include "RegEntry.h"
3.在MainFrm的析构函数中执行注册表的信息清理工作:
首先,获取本程序自定义的文档类型。我在网上没找着相应的解决方案,于是自己根据mfc的api自己编了一个,希望大家不要见笑,更希望大家能够提供更好的解决方案。
POSITION doc_position;
doc_position = AfxGetApp()->GetFirstDocTemplatePosition();
CString type;
AfxGetApp()->GetNextDocTemplate(doc_position)->GetDocString(type,CDocTemplate::filterExt);
然后,使用上述的封装类类删除由EnableShellOpen();RegisterShellFileTypes(TRUE);自动生成的注册表信息。主要有两项:一个以自定义的文档类型名称来命名的节点,另一个是以前一个节点的具体值来命名的节点。具体代码如下:
CRegistry reg(0 & ~CREG_CREATE),reg2(0 & ~CREG_CREATE);
CString info;
if(reg.Open(type,HKEY_CLASSES_ROOT)){
if (reg.GetAt(0)->Exists()){
if(reg.GetAt(0)->IsString())
info.Format("%s",reg.GetAt(0)->operator LPTSTR());
}
if(reg2.Open(info,HKEY_CLASSES_ROOT)){
reg2.DeleteKey();
reg.DeleteKey();
}
}