1. 程式人生 > >windows登錄檔程式設計

windows登錄檔程式設計

Windows登錄檔

1 登錄檔的作用

         登錄檔在windows中非常重要,它是一個龐大的資料庫,裡面儲存了大量的系統資訊,例如儲存軟體硬體的配置資訊,計算機系統的設定,效能記錄。

         如果登錄檔遭到破壞,就可能對整個系統造成影響,甚至系統癱瘓。

2 登錄檔的結構

登錄檔是樹狀的層次結構:主鍵-->子鍵-->子鍵-->子鍵-->……-->鍵值。其中每一個鍵都有鍵值,鍵值由3部分構成:值名,值型別,值本身值。有點像int x =0的節奏哈。 每個鍵都有一個預設的值,所以的預設值就是說這個值沒有名字。當然可以為這個鍵再增加其他值,前提是這些值得有名字。


3 登錄檔的主鍵

<1>HkEY_USERS

<2>HKEY_CURRENT_USER

<3>HKEY_CURRENT_CONFIG

<4>HKEY_CLASSES_ROOT

<5>HKEY_LOCAL_MACHINE

<6>HKEY_DYN_DATA

         這個鍵儲存了系統在執行時候的動態資料,因為每次顯示的時候都是變化的,所以此根鍵下的資訊沒有放在登錄檔中。

4訪問登錄檔的許可權

         有時候程式執行時候會出現如下的錯誤,例如下面的程式碼:

LONG x1 =RegCreateKey(HKEY_LOCAL_MACHINE,TEXT("software\\VC++MFC\\adminss"

),&hKey);

執行之後 x1 = 5,對應的錯誤資訊就是“拒絕訪問”。當然這句程式執行後不會在登錄檔中建立鍵,原因就是前面的說的沒有許可權,具體就是當前登陸的使用者沒有許可權訪問登錄檔。

解決方法:

登錄檔-->編輯-->許可權-->新增(組和使用者名稱)-->輸入物件名稱來選擇-->檢查名稱-->確定


然後就會在組和使用者列表中出現了你所新增的賬戶名。單擊它,檢視它具有的操作登錄檔的許可權。

5 訪問登錄檔的常用函式

         我們可以像訪問檔案一樣,對登錄檔進行鍵值建立,鍵值開啟,鍵值讀取,鍵值寫的操作。常用的函式如下所示:

<1>RegCreateKey

LONG WINAPI RegCreateKey(
 _In_               HKEY       hKey,
 _In_opt_       LPCTSTR          lpSubKey,
 _Out_            PHKEY    phkResult
);

返回值:表示登錄檔訪問失敗的錯誤ID,只有返回值是ERROR_SUCCRSS(0)表示成功訪問,其他都表示各種各樣的錯誤。

hKey:指向當前開啟表項的控制代碼,或者預定義的保留控制代碼之一,HKEY_CLASSES_ROOT,HKEY_USERS,HKEY_CURRENT_USER,HKEY_CURRENT_CONFIG,HKEY_LOCAL_MACHINE.

lpSubKey:一個空’\0’結束的字串,表示要建立或者開啟的鍵的名稱

phkResult:返回值,指向要建立或者開啟的鍵的控制代碼。不再使用時用RegCloseKey函式關閉。

示例:

RegCreateKey(HKEY_LOCAL_MACHINE,TEXT("software\\VC++MFC\\adminss"),&hKey);

結果:


執行程式我們可以在登錄檔中看到新建立的鍵

<2>RegOpenKey

LONG WINAPI RegOpenKey(
  _In_            HKEY     hKey,
  _In_opt_        LPCTSTR  lpSubKey,
  _Out_           PHKEY    phkResult
);

hKey,lpSubKey同RegCreateKey中的同名引數,phkResult表示當前開啟的鍵值的控制代碼

<3>RegSetValue

LONG WINAPI RegSetValue(
  _In_      HKEY     hKey,
  _In_opt_      LPCTSTR  lpSubKey,
  _In_      DWORD    dwType,
  _In_      LPCTSTR  lpData,
  _In_      DWORD    cbData
);

hKey,lpSubKey同上面函式。另外一個鍵的值有三個屬性,值名字,值型別,值本身值。這個函式設定的鍵是預設值(沒有名字),dwType表示值型別,lpData表示設定的值,cbData表示當前設定值的長度。

注意:當lpSubKey = NULL的時候,此時設定的值是控制代碼hKey表示的鍵的值。

<4>RegSetValueEx

當要設定鍵的有名字的知道時候,就需要使用這個函數了

LONG WINAPI RegSetValueEx(
  _In_            HKEY      hKey,
  _In_opt_        LPCTSTR  lpValueName,
  _Reserved_    DWORD    Reserved,
  _In_            DWORD    dwType,
  _In_            const BYTE *lpData,
  _In_            DWORD    cbData
);

lpValueName:表示鍵的名字

Reserved:保留值,必須設為0

dwType:值型別。可以為REG_SZ,REG_DWORD,等等

lpData:值的值,指向一個緩衝區,代表值的值

cbData:lpData引數指向資料的大小,單位是位元組

示例如下:

RegSetValueA(hKey,NULL,REG_SZ,TEXT("fun for Test"),strlen(TEXT("fun for Test")) );
RegSetValueA(hKey,TEXT("Test"),REG_SZ,TEXT("fun for fun"),strlen(TEXT("fun for fun")) );
RegSetValueExA(hKey,TEXT("Test1"),0,REG_SZ,(const BYTE*)TEXT("funforname"),strlen(TEXT("fun forname")));
 
HKEY keyTest;
//LONG x= RegOpenKey(HKEY_LOCAL_MACHINE,TEXT("Test"),&keyTest);
RegOpenKey(HKEY_LOCAL_MACHINE,TEXT("software\\vc++mfc\\adminss\\Test"),&keyTest);
RegSetValueEx(keyTest,TEXT("Test2"),0,REG_SZ,(const BYTE*)TEXT("Test'sname value"),strlen(TEXT("Test'sname value")));

結果:

同時也說明了在設定鍵值的時候,如果不存在鍵值就會建立鍵值。

<5>RegQueryValue

LONG WINAPI RegQueryValue(
  _In_            HKEY     hKey,
  _In_opt_        LPCTSTR  lpSubKey,
  _Out_opt_       LPTSTR   lpValue,
  _Inout_opt_     PLONG    lpcbValue
);

hKey:指定的鍵控制代碼,或者預留的5大主鍵控制代碼

lpSubKey:子鍵的名字,當為NULL的時候表示的查詢hKey代表的鍵預設值

lpValue:返回值

lpcbValue:指定lpValue代表的緩衝區的大小。僅僅是存放值的大小

<6> RegQueryValueEx

用這個可以查詢鍵值有名字的時候的值

LONG WINAPI RegQueryValueEx(
  _In_            HKEY     hKey,
  _In_opt_        LPCTSTR  lpValueName,
  _Reserved_      LPDWORD  lpReserved,
  _Out_opt_       LPDWORD  lpType,
  _Out_opt_       LPBYTE   lpData,
  _Inout_opt_     LPDWORD  lpcbData
);

lpValue:值的名字

lpReserved:保留值,必須為NULL

lpType:返回值,表示值的型別

lpData:返回值,表示值的自身內容

lpcbData:確定值自身內容的大學,不能設定為NULL

6 完整的函式程式碼:

void CmfcFileView::OnRegWrite()
{
         // TODO: 在此新增命令處理程式程式碼
         HKEY hKey;
         LPSTR buf;
         LONG x1 =RegCreateKey(HKEY_LOCAL_MACHINE,TEXT("software\\VC++MFC\\adminss"),&hKey);
         FormatMessage(
                   FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM,NULL ,x1,
                   MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),(LPTSTR)&buf,0,NULL);
         LocalFree(buf);
        
         RegSetValueA(hKey,NULL,REG_SZ,TEXT("fun for Test"),strlen(TEXT("fun for Test")) );
         RegSetValueA(hKey,TEXT("Test"),REG_SZ,TEXT("fun for fun"),strlen(TEXT("fun for fun")) );
         RegSetValueExA(hKey,TEXT("Test1"),0,REG_SZ,(const BYTE*)TEXT("funfor name"),strlen(TEXT("fun forname")));
 
         HKEY keyTest;
         //LONG x =RegOpenKey(HKEY_LOCAL_MACHINE,TEXT("Test"),&keyTest);
         RegOpenKey(HKEY_LOCAL_MACHINE,TEXT("software\\vc++mfc\\adminss\\Test"),&keyTest);
         RegSetValueEx(keyTest,TEXT("Test2"),0,REG_SZ,(const BYTE*)TEXT("Test'sname value"),strlen(TEXT("Test'sname value")));
 
 
         RegCloseKey(hKey);
         RegCloseKey(keyTest);
}
 
 
void CmfcFileView::OnRegRead()
{
         // TODO: 在此新增命令處理程式程式碼
         //get thedefault value of the key
         LONG sz;
         RegQueryValue(HKEY_LOCAL_MACHINE,TEXT("software\\vc++mfc\\adminss\\test"),NULL,&sz);
         TCHAR* pv = newTCHAR[sz];
         RegQueryValue(HKEY_LOCAL_MACHINE,TEXT("software\\vc++mfc\\adminss\\test"),pv,&sz);
         deletepv;
         pv = NULL;
 
         //get thename value of the key
         DWORD sb,dwType;
         TCHAR v[20];
         HKEY hKey;
         RegOpenKey(HKEY_LOCAL_MACHINE,TEXT("software\\vc++mfc\\adminss\\test"),&hKey);
         //RegQueryValueEx(hKey,TEXT("test2"),NULL,&dwType,(LPBYTE)v,&sb);//ok
         RegQueryValueEx(hKey,TEXT("test2"),NULL,&dwType,NULL,&sb);
         TCHAR* ps = newTCHAR[sb]();
         RegQueryValueEx(hKey,TEXT("test2"),NULL,&dwType,(LPBYTE)ps,&sb);//cann't pass NULL to the last parameter
 
         deleteps;
         ps = NULL;
         RegCloseKey(hKey);
}