(我把本文放在這裏,其實最主要的目的是怕自己以後忘了,畢竟我也不常用這方面的知識,好不容易弄懂了點點,就趕快存起來,呵呵^_^)
一、說明:
註冊表是Windows重要組成部分,註冊表記錄了大量有關電腦軟硬件的信息。註冊表中的值通過其名稱標識。值名稱由與鍵名相同的字符組成。值本身可以是字符串、二進制數據或者是32位無符號值。在這裏我們主要運用以下技巧:
(一)、預定義的註冊表鍵。註冊表包含了幾個預定義鍵:
1. HKEY_LOCAL_MACHINE 包含描述計算機及其配置的條目。其中包括關於處理器、系統主板、內存和已安裝的軟件和硬件的信息。
2. HKEY_CLASSES_ROOT 是與文檔類型和 OLE/COM 相關的信息的支持鍵。這個鍵是 HKEY_LOCAL_MACHINE的從屬鍵。
3. HKEY_USERS 用作默認用戶首選設置,也作爲單個用戶的首選設置。
4. HKEY_CLASSES_USER 是用於當前(登錄)用戶的相關信息。
5. HKEY_CURRENT_CONFIG 包含了當前系統配置的信息。
6. 還有一個,一般不會出現,只有配置的局域網後纔會有。
(二)、VC中兩種註冊表操作方法
在VC中,主要有兩種方法可以實現註冊表的操作,一是使用MFC封裝的類CRegKey,該類包含了14個成員函數,它們可以實現註冊表的簡單操作(基本的如本文提到的“打開、創建、讀、寫、關閉”等);二是使用Windows API函數。當然,對我來說,能使用底層的,那爲什麼不用呢,畢竟我現在是程序員,使用底層函數,可以移植到更多的開發平臺中嘛。
1.
所需要頭文件:atlbase.h
該種方法可以使用類CRegKey中的成員函數來完成。先包含頭文件,再申明一個類對象CRegKey RKey;然後就可以調用成員函數來操作了。
基本功能的成員函數:
LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName,REGSAM samDesired = KEY_ALL_ACCESS);
LONG Close();
LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE,
REGSAM samDesired = KEY_ALL_ACCESS,
LPSECURITY_ATTRIBUTES lpSecAttr = NULL,
LPDWORD lpdwDisposition = NULL);
LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName);
LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
LONG QueryValue(DWORD& dwValue, LPCTSTR lpszValueName);
LONG QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount);
其他幾個:
LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName,LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
HKEY Detach();
void Attach(HKEY hKey);
LONG DeleteSubKey(LPCTSTR lpszSubKey);
LONG RecurseDeleteKey(LPCTSTR lpszKey);
LONG DeleteValue(LPCTSTR lpszValue);
但是本文主要介紹使用Windows API函數來操作註冊表,所以這裏不詳細的介紹這些成員函數的用法了。
2. Windows API函數個數比較多,一共有三、四十個,這裏主要介紹幾個常用的函數,來實現本文所說的基本功能即可。
常用API函數
☆ 打開一個鍵的函數:RegOpenKeyEx
函數定義:LONG RegOpenKeyEx(HKEY hKey,//已經打開的鍵的句柄,或者直接是上述幾個根鍵
LPCTSTR lpSubKey,//要打開的子鍵名字的地址
DWORD ulOptions,//保留值,必須爲0
REGSAM samDesired,//打開方式,如讀還是寫
PHKEY phkResult//返回的打開的子鍵的句柄
);
說明:如果指定的要打開的子鍵不存在,則返回失敗;反之返回成功ERROR_SUCCESS;
☆ 創建一個鍵的函數:RegCreateKeyEx
函數定義:LONG RegCreateKeyEx(HKEY hKey,//已經打開的鍵的句柄,或者直接是上述幾個根鍵
LPCTSTR lpSubKey,//要創建的子鍵名字的地址
DWORD ulOptions,//保留值,必須爲0
REGSAM samDesired,//打開方式,如讀還是寫
PHKEY phkResult//返回的創建的子鍵的句柄
);
說明:如果指定的要創建的子鍵已經存在,則打開該子鍵;反之創建該子鍵。函數成功則返回ERROR_SUCCESS;
該子鍵可以一次創建多層子鍵,格式爲“子鍵1層//子鍵2層//子鍵3層。。。”
☆ 查詢某一個鍵值:RegQueryValueEx
函數定義:LONG RegQueryValueEx(HKEY hKey,//要查詢的鍵的句柄
LPCTSTR lpValueName,//要查詢的鍵值的名稱
LPDWORD lpReserved,//保留值,必須爲0
LPDWORD lpType,//要查詢的數據的類型,如果不關心,可以爲NULL
LPBYTE lpData,//要返回的查詢的數據
LPDWORD lpcbData//預置的數據的長度,理論上可以爲NULL,但實際我發現不行,最好設一個值
);
☆ 設置一個鍵值RegSetValueEx
函數定義:LONG RegSetValueEx(HKEY hKey,//要設置的鍵的句柄
LPCTSTR lpValueName,//要訪問的鍵值的名稱
LPDWORD lpReserved,//保留值
DWORD dwType,//要設置的數據的類型
const BYTE *lpData,//要設置的健值
DWORD cbData//數據的長度
);
說明:如果要寫入的數據已經存在,只是改變值而已;如果不存在,則新建子鍵並存值。
二、例子
我做了一些註冊表的簡單操作,主要是打開,如果打開失敗,則創建;然後存值;
HKEY key;
CString strName = "hello";
CString strCompany = "world";
CString strSeries = "1111-1111";
bool G_bIsLicesed = true;
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software//my Application//Settings"), 0, KEY_ALL_ACCESS, &hkey)!= ERROR_SUCCESS)
{
VERIFY(!RegCreateKey(HKEY_CURRENT_USER, _T("Software//my Application//Settings"), &hkey));
}
VERIFY(!RegSetValueEx(hkey, _T("LicesedBool"), 0, REG_DWORD, (BYTE *)&G_bIsLicesed, 4));
VERIFY(!RegSetValueEx(hkey, _T("User Name"), 0, REG_SZ, (BYTE *)strName.GetBuffer(strName.GetLength()), 50));
VERIFY(!RegSetValueEx(hkey, _T("Company Name"), 0, REG_SZ, (BYTE *)strCompany.GetBuffer(strCompany.GetLength()),25));
VERIFY(!RegSetValueEx(hkey, _T("License Code"), 0, REG_SZ, (BYTE *)strSeries.GetBuffer(strSeries.GetLength()), 20));
RegCloseKey(hkey);
另外,我還做了註冊表的讀取操作
unsigned char chbuf[50];
CString strCompany = "";
CString strSeries = "";
HKEY hkey;
DWORD type(0);
DWORD len(50);
memset(chbuf, 0, sizeof(chbuf));
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software//my Application//Settings"), 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hkey, _T("User Name"), 0, &type, chbuf, &len) == ERROR_SUCCESS)
{
;
}
if (!RegQueryValueEx(hkey, _T("Company Name"), 0, &type, chbuf, &len))
{
strCompany.Format("%s", chbuf);
}
if (!RegQueryValueEx(hkey, _T("License Code"), 0, &type, chbuf, &len))
{
strSeries.Format("%s", chbuf);
}
if (!RegQueryValueEx(hkey, _T("LicesedBool"), 0, &type, chbuf, &len))
{
G_bIsLicesed = chbuf[0];
}
RegCloseKey(hkey);
}
先就到這裏吧,如果要求不是很高的話,就“依葫蘆畫瓢”,基本可是實現本文所說的功能了。
如果有朋友來看了本文,而你又有更詳盡更使用的東東,請貼上來,不盡感謝!
還特別說明一點,就是從註冊表中取值的時候,一定記得
RegQueryValueEx(hkey, _T("LicesedBool"), 0, &type, chbuf, &len)
函數中的參數len,它的大小必須能夠容納要取的值的內存大小。
也就是說,比如要取一個字符串,長爲100,那麼,你在調用該函數前必須爲len定義一個值,該值大於等於100,否則,它取值會失敗!
len返回值是實際取值的長度,但是傳入之前必須定義一個大於該長度的值,否則它雖然仍會返回實際長度的值,可是數據確取不 出來。
我上面的代碼,實際就有點失誤。用同一個len連續用在三個取值函數中,雖然開始是設定了值的,可是一旦在前面或中間某個取值函數中返回的len值小於後面一個取值函數中的len實際值,那麼後面那個取痔函數就取不 出來值而且,這種失誤也是很難檢測出來的,因爲它的語法沒有任何錯誤。必須時刻注意!!!