26 장. 레지스트리 26-1 INI 파일 26-2 레지스트리 Windows API
26-1 INI 파일 정보의 저장
함수 BOOL WritePrivateProfileString ( LPCTSTR lpAppName // 기록할 섹선이름, LPCTSTR lpKeyName // 기록할 키이름 NULL- 섹션삭제,LPCTSTR lpString // 키값을 정의하는 문자열, LPCSTR lpFileName //ini 파일명 )
UINT GetPrivateProfileInt ( LPCTSTR lpAppName, // 기록할 섹선이름 LPCTSTR lpKeyName, // 기록할 키이름 NULL- 섹션삭제 INT nDefault, // 디폴트 값 LPCTSTR lpFileName //ini 파일명 )
DWORD GetPrivateProfileString ( LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPTSTR lpReturnedString, // 문자열을대입받을버퍼 DWORD nSize, // 버퍼의크기 LPCSTR lpFileName, )
inifile
Left+X,Top+Y,Right+X,Bottom+Y
26-2 레지스트리 가.INI 파일의 단점 1. 텍스트파일 포맷으로 저장 - 사용자임의조작가능 -> 오작동 가능 성. 2. 디스크공간 낭비 3. 복수사용자 지원하지 않음. 4. 손상시 복구 불가. 5. 느리다.
LONG RegCreateKeyEx( HKEY hKey, // 새로 만들어 지는 키의 부모키 LPCTSTR lpSubKey, // "Software\\KanamSoft\\RegiTest\\Position", DWORD Reserved, // 예약된 인수 LPTSTR lpClass, // 생성된 키의 클래스 지정 DWORD dwOption, // 생성하는 키의 옵션 REGSAM samDesired, // 키의 보안속성 LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 생성된 키값이 차일드로 상속될것인가 ? NULL- 상속안됨 PHKEY phkResult, // 키값이 대입되는 변수 포인터 LPDWORD lpdwDisposition // 생성되었는지 오픈되었는지 출력 용변수 )
LONG RegSetValueEx( HKEY hKey, LPCTSTR lpvalueName, // 값의 이름지정 DWORD Reserved, DWORD dwType, CONST BYTE *lpData, // 저장하고자하는 데이터 DWORD cbData )
LONG RegQueryValueEx( HKEY hKey, LPTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, // 읽을값의 타입받을변수포인터 LPBYTE lpData, LPDWORD lpcbData //lpData 의 크기 )
LONG RegCloseKey(HKEY hKey) LONG RegOpenKeyEx( HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, PHKEY phkResult )
Regi LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) { RECT rt; HKEY key; DWORD dwDisp; DWORD Size; switch(iMessage) { case WM_CREATE: RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\KanamSoft\\RegiTest\\Position",0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL,&key,&dwDisp); Size=sizeof(LONG); if (RegQueryValueEx(key, "Left", 0, NULL,(LPBYTE)&rt.left, &Size) !=ERROR_SUCCESS) rt.left=0; Size=sizeof(LONG); if (RegQueryValueEx(key, "Top", 0, NULL,(LPBYTE)&rt.top, &Size) !=ERROR_SUCCESS) rt.top=0;
Size=sizeof(LONG); if (RegQueryValueEx(key, "Right", 0, NULL,(LPBYTE)&rt.right, &Size)!=ERROR_SUCCESS) rt.right=100; Size=sizeof(LONG); if (RegQueryValueEx(key, "Bottom", 0, NULL,(LPBYTE)&rt.bottom, &Size) !=ERROR_SUCCESS) rt.bottom=100;; RegCloseKey(key); MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); return 0;
case WM_DESTROY: RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\KanamSoft\\RegiTest\\Position",0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL,&key,&dwDisp); GetWindowRect(hWnd, &rt); RegSetValueEx(key, "Left",0,REG_DWORD,(LPBYTE)&rt.left, sizeof(LONG)); RegSetValueEx(key, "Top",0,REG_DWORD,(LPBYTE)&rt.top, sizeof(LONG)); RegSetValueEx(key, "Right",0,REG_DWORD,(LPBYTE)&rt.right, sizeof(LONG)); RegSetValueEx(key, "Bottom",0,REG_DWORD, (LPBYTE)&rt.bottom,sizeof(LONG)); RegCloseKey(key); PostQuitMessage(0); return 0; } return(DefWindowProc(hWnd,iMessage,wParam,lParam)); }
26-3 레지스트리 관리 가. 미리정의된 키 –HKEY_USER –HKEY_LOCAL_MACHINE –HKEY_CURRENT_USER –HKEY_CLASSES_ROOT –HKEY_CURRENT_CONFIG
나. 비우기 LONG RegFlushKey( HKEY hKey ) 다. 삭제 LONG RegDeleteKey(HKEY hKey, LPCTSTR lpValueName )
라. 정보조사 LONG RegQueryInfoKey( HKEY hKey, // 조사하고자하는 키의 핸들 LPTSTR lpClass, // 클래스 스트링 LPDWORD lpcbClass, // 클래스 스트링의 버퍼크기 LPDWORD lpReserved, // 예약 LPDWORD lpcSubKeys, // 서브키의 개수 LPDWORD lpcbMaxSubKeyLen, // 가장긴이름의 서브키의 길이 LPDWORD lpcbMaxClassLen, // 가장 긴 이름의 클래스길이 LPDWORD lpcValues, // 값의 개수 LPDWORD lpcbMaxValueNameLen, // 가장긴 이름의 값길이 LPDWORD lpcbMaxValueLen, // 가장 긴 데이터길이 LPDWORD lpcbSecurityDescriptor, // 보안속성의 길이 PFILETIME lpftLastWriteTime // 최후수정시간 );
마. 열거 LONG RegEnumKeyEx( HKEY hKey, // handle to key to enumerate DWORD dwIndex, // index of subkey to enumerate LPTSTR lpName, // address of buffer for subkey name LPDWORD lpcbName, // address for size of subkey buffer LPDWORD lpReserved, // reserved LPTSTR lpClass, // address of buffer for class string LPDWORD lpcbClass, // address for size of class buffer PFILETIME lpftLastWriteTime // address for time key last written to );
LONG RegEnumValue( HKEY hKey, // handle to key to query DWORD dwIndex, // index of value to query LPTSTR lpValueName, // address of buffer for value string LPDWORD lpcbValueName, // address for size of value buffer LPDWORD lpReserved, // reserved LPDWORD lpType, // address of buffer for type code LPBYTE lpData, // address of buffer for value data LPDWORD lpcbData // address for size of data buffer );
RegEnum void RegEnum(HKEY); void DblClk(void); void SelChange(void); // 차일드 컨트롤들 #define ID_LISTBOX 100 #define ID_EDIT 101 #define ID_BUTTON 102 HWND hList; HWND hEdit; HWND hButton; HWND hStatic; LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) {HKEY key; char str[MAX_PATH]; switch(iMessage) {
// 차일드 윈도우를 만든다. case WM_CREATE: hList=CreateWindow("listbox",NULL,WS_CHILD | WS_VISIBLE | WS_BORDER |LBS_NOTIFY | WS_VSCROLL, 10,50,200,400,hWnd,(HMENU)ID_LISTBOX,g_hInst,NULL); hEdit=CreateWindow("edit","software",WS_CHILD | WS_VISIBLE | WS_BORDER |ES_AUTOHSCROLL, 10,10,400,25,hWnd,(HMENU)ID_EDIT,g_hInst,NULL); hButton=CreateWindow("button","Enumerate",WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,420,10,100,25, hWnd,(HMENU)ID_BUTTON,g_hInst,NULL); hStatic=CreateWindow("static"," 표시할 내용이 없습니다.", WS_CHILD | WS_VISIBLE,,0,0,0,0,hWnd,(HMENU)-1,g_hInst,NULL); // 프로그램 시작 직후에 software 아래의 키를 조사한다. SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(ID_BUTTO N,BN_CLICKED),(LPARAM)hButton); return 0;
case WM_COMMAND: switch (LOWORD(wParam)) { // 버튼 누름 : 에디트의 키값으로 순회한다. case ID_BUTTON: GetWindowText(hEdit,str,MAX_PATH); if (RegOpenKeyEx(HKEY_CURRENT_USER, str,0,KEY_ALL_ACCESS,&key) == ERROR_SUCCESS) { RegEnum(key); RegCloseKey(key); } else { MessageBox(hWnd," 지정한 키를 열 수 없습 니다 "," 에러 ",MB_OK); } break; // 리스트 박스의 클릭과 더블 클릭 처리 case ID_LISTBOX: switch (HIWORD(wParam)) { case LBN_DBLCLK: DblClk(); break;
case LBN_SELCHANGE: SelChange(); break; } break; } return 0; case WM_SIZE: MoveWindow(hEdit,10,10,LOWORD(lParam)-130,25,TRUE); MoveWindow(hButton,LOWORD(lParam)- 110,10,100,25,TRUE); MoveWindow(hList,10,50,LOWORD(lParam)- 20,HIWORD(lParam)-80,TRUE); MoveWindow(hStatic,10,HIWORD(lParam)- 30,LOWORD(lParam)-20,25,TRUE); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return(DefWindowProc(hWnd,iMessage,wParam,lParam)); }
void RegEnum(HKEY key) { char lpSubKey[MAX_PATH]; char lpValue[MAX_PATH]; char lpBuffer[MAX_PATH]; DWORD i; LONG Result; DWORD Size; FILETIME FileTime; SendMessage(hList,LB_RESETCONTENT,0,0); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)" ^^^ 한 단계 위 로 ^^^ "); // 서브키의 목록의 조사해 리스트 박스에 채워 넣는다. Result=ERROR_SUCCESS; for (i=0;Result==ERROR_SUCCESS;i++) { Size=MAX_PATH;
Result=RegEnumKeyEx(key,i,lpSubKey,&Size,NULL,NULL,NULL,& FileTime); if (Result==ERROR_SUCCESS) { wsprintf(lpBuffer,"K : %s",lpSubKey); SendMessage(hList,LB_ADDSTRING,0,(LONG)lpBuffer); } // 값의 목록을 조사해 리스트 박스에 채워 넣는다. Result=ERROR_SUCCESS; for (i=0;Result==ERROR_SUCCESS;i++) { Size=MAX_PATH; Result=RegEnumValue(key,i,lpValue,&Size,NULL,NULL,NULL,NULL); if (Result==ERROR_SUCCESS) { wsprintf(lpBuffer,"V : %s",lpValue); SendMessage(hList,LB_ADDSTRING,0,(LONG)lpBuffer); }
void DblClk(void) { int index; char buffer[MAX_PATH]; char Caption[MAX_PATH]; char Post[MAX_PATH]; char *backslash; index=SendMessage(hList,LB_GETCURSEL,0,0); // 한단계 위로 처리 if (index==0) { GetWindowText(hEdit,Caption,MAX_PATH); backslash=strrchr(Caption, '\\'); if (backslash==NULL) { MessageBox(g_hWndMain," 더 올라갈 곳이 없습니다요 "," 잠깐 !",MB_OK); return; } backslash[0]=0; SetWindowText(hEdit,Caption);
SendMessage(g_hWndMain,WM_COMMAND, MAKEWPARAM(ID_BUTTON,BN_CLICKED),(LPARAM)hButt on); return; } // 키를 더클릭했을 경우 해당 키를 조사한다. SendMessage(hList,LB_GETTEXT,index,(LPARAM)buffer); strcpy(Post,buffer+4); if (buffer[0]=='K') { GetWindowText(hEdit,Caption,MAX_PATH); wsprintf(buffer,"%s\\%s",Caption,Post); SetWindowText(hEdit,buffer); SendMessage(g_hWndMain,WM_COMMAND,MAKEWPARA M(ID_BUTTON,BN_CLICKED), (LPARAM)hButton); }
void SelChange(void) { int index; char buffer[MAX_PATH]; char Caption[MAX_PATH]; char Post[MAX_PATH]; HKEY key; DWORD cSubKeys, cValues; DWORD Type, Size; BYTE Data[MAX_PATH]; index=SendMessage(hList,LB_GETCURSEL,0,0); // 한단계 위로에 대해서는 전혀 반응하지 않는다. if (index==0) return; SendMessage(hList,LB_GETTEXT,index,(LPARAM)buffer); strcpy(Post,buffer+4);
// 키에 속한 서브키와 값의 개수 조사 if (buffer[0]=='K') { GetWindowText(hEdit,Caption,MAX_PATH); wsprintf(buffer,"%s\\%s",Caption,Post); if (RegOpenKeyEx(HKEY_CURRENT_USER, buffer,0,KEY_ALL_ACCESS,&key) == ERROR_SUCCESS) { RegQueryInfoKey(key,NULL,NULL,NULL,&cSubKeys,NULL,NULL,&cValues,NULL,NULL,NULL,NULL); RegCloseKey(key); wsprintf(Caption," 서브키의 수 :%d, 값의 수 :%d",cSubKeys,cValues); SetWindowText(hStatic,Caption); }
else if (buffer[0]=='V') { GetWindowText(hEdit,Caption,MAX_PATH); if (RegOpenKeyEx(HKEY_CURRENT_USER, Caption,0,KEY_ALL_ACCESS,&key) == ERROR_SUCCESS) { Size=MAX_PATH; RegQueryValueEx(key,Post,NULL,&Type,Data,&Size); RegCloseKey(key); switch (Type) { case REG_DWORD: wsprintf(Caption," 데이터 타입 : 정수형, 데이 터 :%d",*(LPDWORD)Data); break; case REG_SZ: wsprintf(Caption," 데이터 타입 : 문자열, 데이 터 :%s",Data); break; default: wsprintf(Caption," 데이터 타입 :%d, 데이 터 :%s",Type,Data); break; } SetWindowText(hStatic,Caption); }