# Shkenca > Informatikë dhe Internet > Arti i programimit >  VB - Si te Krijojme Çelesa Regjistri ne Menyre Programatike

## Borix

*Si te Krijojme Çelesa Regjistri ne Menyre Programatike*


*Hyrje dhe Koncepte Baze*

Regjistri i sistemit Windows u shfaq per here te pare ne Windows 3.1, nen emrin reg.dat, si nje menyre alternative dhe moderne per te ruajtur informacion rreth objekteve OLE. Perkufizuar shkurtimisht, regjistri i sistemit eshte si nje "magazine" qe mban te dhena per harduerin e instaluar, sistemin operativ, programet aplikative, dhe perdoruesit.

Te gjithe ne kemi hasur skedaret e konfigurimit me ekstensionin '.INI', vecanerisht ne perfaqesimin e drajverave harduerike, si dhe te jo pak sistemeve te tjera. Regjistri eshte nje zevendesues i mirefillte i ketyre skedareve, duke 'grumbulluar' informacionin nen nje sistem te vecante. Sigurisht, kjo metode shpalos avantazhe ndaj perdorimit te skedareve te konfigurimit. Se pari, programet e kane me te thjeshte te aksesojne informacionin, sepse ky i fundit eshte i centralizuar. Se dyti, meqenese informacioni paraqitet ne menyre hierarkike, sasi te medha te dhenash mund te ruhen ne forme shume here me te strukturuar se sa ne skedaret INI. 

Nga ky kendveshtrim, regjistri eshte nje zgjedhje preferenciale mbi perdorimin e skedareve te konfigurimit nga shume programe dhe sisteme aplikative, si dhe nga shume programues. Ne kete artikull, do te paraqes metoda rreth krijimit, azhurnimit, leximit, dhe fshirjes se celesave ne regjister ne menyre programatike, duke dhene edhe kodin (ne VB6, por i pergjithesueshem) qe kam pershtatur dhe modifikuar gjate viteve te fundit. (Sa here qe permendet fjala regjister, nenkuptohet ai i sistemeve operative Windows 2000/NT e te pasueseve).


*Struktura e Regjistrit*

Megjithese regjistri jep idene e nje sistemi te vetem, fizikisht te dhenat ruhen ne disa skedare te tjere, si system.dat dhe user.dat, te cilat ndodhen ne direktorine e Windows, zakonisht nen dosjen system32. Keto dy skedare grumbullojne te dhena rreth sistemit operativ dhe llogarive te ndryshme te perdorueseve. Per me teper, regjistri eshte i particionuar ne disa skedare te tjere te emeruara, ne menyre figurative, si 'depo' (Ang.- hives, por do t'i referohem kembyeshem edhe si 'çeles'). Prandaj, cdo depo fillon me karakteret HKEY_, strukturohet si nje peme (analogjikisht me Windows Explorer), dhe pasohet nga nje emer, i cili specifikon permbajtjen e kesaj depoje. Pershembull, depo HKEY_ CLASSES_ ROOT ka per qellimi percaktimin dhe gjurmimin e ekstensioneve te skedareve dhe aplikacioneve perkatese. Me tej, depo HKEY_CURRENT_USER permban informacion specifik rreth te gjitha aplikacioneve dhe te dhenave te lidhura me perdoruesin aktual. Ndersa depo HKEY_ LOCAL_ MACHINE, magazinon nje sasi te madhe te dhenash te posacme te kompjuterit (mashinës). Celesa te tjere jane HKEY_ USERS (te dhena mbi perdoruesit), HKEY_ CURRENT_ CONFIG (detaje te softeve te instaluara), dhe HKEY_ DYN_ DATA (kopje e drejtperdrejte e disa artikujve te tjere).

Emrat dhe vlerat e celesave ne regjister mund te ndryshohen sipas rastit, mund te fshihen, ose mund te krijohen celesa dhe vlera te reja. Dy tipet e vetme te te dhenave jane REG_DWORD, per vlera numerike dhe REG_SZ, per karaktere - String. (_Per me teper informacion rreth arkitektures dhe operacioneve te ndryshme mbi celesat e regjistrit, lexoni tutorialin e ben7/11._)


*Shfrytezimi i Regjistrit gjate Zhvillimit te Programeve*

Shpeshhere, programuesit hasen me specifikime te shumta rreth konfigurimit te sistemeve qe kerkohet te zhvillohen. Per shembull, nese nje perdorues kerkon te shohe nje forme te caktuar te programit ne nje pozicion te caktuar sa here qe e ngarkon ate forme ne memorie, atehere nje ide e mire eshte te ruhen diku koordinatat top dhe left te formes dhe, pergjithesisht, preferencat e tjera te paparashikueshme te perdorueseve. Nga njera ane, mund te perdoren skedare INI, por kjo nuk do te rezultonte aspak praktike per te vetmen aryse mbingarkimi i punes gjate komunikimit me skedarin fizik. Nga ana tjeter, nje praktike me e sakte dhe me e shpejte do te ishte shfrytezimi i regjistrit. Kjo e fundit realizohet fale procedurave te inkorporuara API (Application Program Interface), te cilat paraqesin, nder vecori te tjera, edhe profesionalizem. Keto rutina te paracaktuara e zgjerojne funksionalitetin e vete gjuhes se programimit dhe jane te pavarura nga njera gjuhe ne tjetren (flitet per platformat e Microsoft). Me tej do te aludoj mbi aplikimin e funksioneve API (pa hyre ne detajet teknike perkatese) duke perdorur VB6 (per thjeshtesi), si dhe do te paraqes disa pika nga mundesite e shfrytezimit bazuar mbi eksperiencen time dhe te te tjereve.


_Deklarime te pergjithshme (ne nje module .bas)_



```
Option Explicit

' Konstantja e meposhtme sherben per te kapur gabime qe lindin nga konvertimi i tipeve
' (per shembull, nga tekst ne numer dhe anasjelltas):
Public Const STR2NUM_CAST_ERROR = 13

' Deklarojme disa konstante kryesore si dhe funksionet API

Public Const REG_SZ As Long = 1     ' tipi string (Unicode)
Public Const REG_DWORD As Long = 4  ' tipi numerik

' Depot e regjistrit
Public Const HKEY_CLASSES_ROOT = &H80000000
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_USERS = &H80000003

' Konstante e gabimeve qe mund te lindin
Public Const NO_ERROR = 0&
Public Const ERROR_BADDB = 1
Public Const ERROR_BADKEY = 2
Public Const ERROR_CANTOPEN = 3
Public Const ERROR_CANTREAD = 4
Public Const ERROR_CANTWRITE = 5
Public Const ERROR_OUTOFMEMORY = 6
Public Const ERROR_ARENA_TRASHED = 7
Public Const ERROR_ACCESS_DENIED = 8
Public Const ERROR_INVALID_PARAMETERS = 87
Public Const ERROR_NO_MORE_ITEMS = 259

Public Const KEY_QUERY_VALUE = &H1
Public Const KEY_SET_VALUE = &H2
Public Const KEY_ALL_ACCESS = &H3F
Public Const KEY_READ = &H20019

Public Const REG_OPTION_NON_VOLATILE = 0

' Deklarimet e funksioneve API per regjistrin 32b

' Funksioni per te perfunduar referencen ndaj celesit ne nje depo te dhene
Private Declare Function RegCloseKey Lib "advapi32.dll" _
         (ByVal hKey As Long) As Long

' Funksioni per te krijuar nje celes ne nje depo te dhene: 
Private Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" _
         (ByVal hKey As Long, ByVal lpSubKey As String, ByVal reserved As Long, _
          ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, _
          ByVal lpSecurityAttributes As Long, phkResult As Long, lpdwDispositions As Long) As Long

' Funksion per te hapur nje celes ne nje depo  te dhene:
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
         (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, _
          ByVal samDesired As Long, phkResult As Long) As Long

' Funksione per te lexuar vlerat e celesit te dhene:
Private Declare Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" _
         (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
          lpType As Long, ByVal lpData As String, lpcbData As Long) As Long

Private Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExA" _
         (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
          lpType As Long, lpData As Long, lpcbData As Long) As Long

Private Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias "RegQueryValueExA" _
         (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
          lpType As Long, ByVal lpData As Long, lpcbData As Long) As Long

' Funksione per te shtuar vlera te celesit, dhene emri i celesit:
Private Declare Function RegSetValueExString Lib "advapi32.dll" Alias "RegSetValueExA" _
         (ByVal hKey As Long, ByVal lpValueName As String, ByVal reserved As Long, _
          ByVal dwType As Long, ByVal lpValue As String, ByVal cbData As Long) As Long

Private Declare Function RegSetValueExLong Lib "advapi32.dll" Alias "RegSetValueExA" _
         (ByVal hKey As Long, ByVal lpValueName As String, ByVal reserved As Long, _
          ByVal dwType As Long, lpValue As Long, ByVal cbData As Long) As Long

' Funksion per te fshire nje celes nga nje depo e dhene:
Private Declare Function ShDeleteKey Lib "shlwapi.dll" Alias "SHDeleteKeyA" _
         (ByVal hKey As Long, ByVal lpSubKey As String) As Long
```

_Komente:_ Konstantet e mesiperme jane dhene ne formen hekzadecimale, sepse celesat ne regjister dhe identifikime i tyre ruhen dhe referohen ne kete menyre nga memoria dhe CPU. Vereni, gjithashtu, deklarimet e funsioneve API, pseudonimet (alias) e tyre, dhe librarinee DLL perkatese: advapi32.dll, qe ndodhet ne direktorine system32. Ne emrin e cdo funksioni ekzistojne karakteret "Ex", te cilat qendrojne per "Extended" dhe tregojne se funksioni eshte shkruar posacerisht per regjistrin e zgjeruar te sistemeve te vona operative (win32).

Me poshte do te paraqes kater procedura publike, brenda te cilave therriten funksionet e mesiperme sipas operacioneve qe kerkohen te kryhen mbi regjistrin.


_Krijimi i Celesit_



```
' 1. KRIJIMI I CELESIT   
Public Sub CreateKey(strKeyName As String, Optional lngPredefKey As Long)
' strKeyName – emri i celesit qe do te krijohet
' lngPredefKey – ne cilen depo do te krijohet, p.sh. ne HKEY_USER

   Dim hNewKey As Long ' reference ndaj celesit qe po krijohet
   Dim lRetVal As Long ' vlere qe kthehet nga funksionet API, per te kapur gabime
   
   ' nese nuk eshte dhene ndonje depo, vendos si vlere fillestare
   ' depon HKEY_CURRENT_USER:
   If lngPredefKey = 0& Then
      lngPredefKey = HKEY_CURRENT_USER
   End If
   
   ' konstantja  KEY_ALL_ACCESS eshte e nevojshme per t’i dhene te gjitha privilegjet:
   lRetVal = RegCreateKeyEx(lngPredefKey, strKeyName, 0&, vbNullString, REG_OPTION_NON_VOLATILE, _
                           KEY_ALL_ACCESS, 0&, hNewKey, lRetVal)
         
   If lRetVal <> NO_ERROR Then
      MsgBox "Celesi " & strKeyName & " nuk mundi te krijohej."
   End If
      
   RegCloseKey (hNewKey) ' Shkaterro referencen ndaj celesit te ri per te cliruar CPU.

End Sub
```


_Komente:_ Procedura Sub publike CreateKey() mund te therritet nga cdo module e nje projekti nen zhvillim, per te krijuar nje celes ne nje depo te caktuar. Pershembull, thirrja CreateKey("Borix\Forumi\Trajnime", HKEY_CURRENT_USER) do te krijonte celesin 'Trajnime', nen celesin 'Forumi', nen celesin 'Borix', nen depon HKEY_CURRENT_USER. Vereni, gjithashtu, se si procedohet per krijimin e celesit: fillimisht, variabli lRetVal ruan vleren qe kthehet nga funksioni API RegCreateKeyEx(), ne menyre qe programuesi te percaktoje nese operacioni u krye me sukses (kur kjo vlere eshte zero), ose jo, dhe cili gabim lindi (ne baze te konstanteve te deklaruara me siper, te cilat ne kete rast jane perjashtuar per arsye te sasise te madhe te kodit).


_Shtimi i nje vlere ne nje celes te dhene_



```
' 2. Futja e vleres se celesit:
Public Sub SetKeyValue(strKeyName As String, strKeyVal As String, vValSetting As Variant, _
                       lValType As Long, Optional lngPredefKey As Long)
' strkeyname - emri i celesit ku do te shtohet vlera
' strKeyVal - emri i vleres (ekuivalent me emrin e nje dosje ne Windows)
' vValSetting - vlera (string ose numerike, prandaj ne VB deklarohet Variant)
' lValType - konstantja e tipit te vleres (REG_DWORD apo REG_SZ)
' lngPredefKey - depo (fakultative). Depo fillestare: HKEY_CURRENT_USER

   Dim hCurKey As Long
   Dim lRetVal As Long
   
   If lngPredefKey = 0& Then
      lngPredefKey = HKEY_CURRENT_USER
   End If
   
   ' hap celesin per te shtuar vleren
   ' Shenim: konstantja KEY_SET_VALUE nevojitet.
   lRetVal = RegOpenKeyEx(lngPredefKey, strKeyName, 0, KEY_SET_VALUE, hCurKey)
   
   ' nese celesi nuk ekziston, krijoje ne baze kerkese
   If lRetVal <> NO_ERROR Then
      If MsgBox("Celesi[" & strKeyName & "] nuk ekziston. Te krijohet? ", _
                  vbYesNo) = vbYes Then
         Call CreateKey(strKeyName, lngPredefKey)
      End If
      Exit Sub
   End If
   
   ' shto vleren tek celesi i sapo hapur ose i sapo krijuar:
   Select Case lValType  ' vlera eshte numerike apo string?
      Case REG_SZ:
         vValSetting = CStr(vValSetting & Chr$(0))
         lRetVal = RegSetValueExString(hCurKey, strKeyVal, 0&, lValType, vValSetting, Len(vValSetting))
      Case REG_DWORD:
         vValSetting = CLng(vValSetting)
         lRetVal = RegSetValueExLong(hCurKey, strKeyVal, 0&, lValType, vValSetting, CLng(4))
   End Select
   
   ' nese na doli ndonje gabim:
   If lRetVal <> NO_ERROR Then
      MsgBox "Vlera " & strKeyVal & " per celesin " & strKeyName & " nuk mund te shkruhej."
   End If
   
End Sub
```

_Komente:_ Celesi i krijuar mund te gjendet ne anen e majte te editorit te regjistrit (i cili mund te hapet me komanden regedit nga Start-Run), ndersa me kete procedure ne krijojme nje vlere te celesit (ne anen e djathte te editorit te regjistrit). Kjo vlere ka dy komponente: emrin e saj, dhe vete vleren numerike ose tekst qe permban. Po te klikohet dy here mbi te, do te shfaqet vlera (ne formatin fillestar hekzadecimal). Gjithashtu, brenda funksionit jepet edhe mundesia per te krijuar nje celes me emrin e dhene, nese ai nuk ekziston.


_Leximi i nje vlere ne nje celes te dhene_



```
' Leximi i nje vlere
Public Function GetKeyValue(strKeyName As String, strValName As String, Optional lngPredefKey As Long) As Variant
' strKeyName - emri i celesit (apo i dosjes nen nje depo te caktuar)
' strValName - emri i vleres se ketij celesi (e cila permban nje vlere brenda saj)

   Dim lRetVal As Long
   Dim hCurKey As Long
   Dim KeyValue As Variant 
   Dim dataType As Long 
   Dim dataSize As Long

   If lngPredefKey = 0& Then
      lngPredefKey = HKEY_CURRENT_USER
   End If
   
   ' hap celesin
   ' Shenim: konstantja KEY_QUERY_VALUE eshte e nevojshme
   lRetVal = RegOpenKeyEx(lngPredefKey, strKeyName, 0, KEY_QUERY_VALUE, hCurKey)
   
   ' nese celesi nuk ekziston, kthe nje vlere te pacaktuar (NULL)
   ' dhe dil nga funksioni
   If lRetVal <> NO_ERROR Then     
      GetKeyValue = vbNullString
      Exit Function
   End If

   ' Nese vlera ekziston, lexoje:
   ' Fillimisht percakto tipin (numerike apo string):
   lRetVal = RegQueryValueExNULL(hCurKey, strValName, 0&, dataType, 0&, dataSize)
   
   If dataType = REG_SZ Then  ' nese eshte string
      Dim strVal As String 
      
      strVal = String(dataSize, 0)
      lRetVal = RegQueryValueExString(hCurKey, strValName, 0&, dataType, strVal, dataSize)
      KeyValue = Left$(strVal, dataSize - 1) 
      
   ElseIf dataType = REG_DWORD Then  ' nese eshte numerike
      Dim lngVal As Long 
      
      lRetVal = RegQueryValueExLong(hCurKey, strValName, 0&, dataType, lngVal, dataSize)
      KeyValue = CLng(lngVal)
      
   Else
      KeyValue = "Gabim, vlera nuk mundi te lexohej."
   End If
   
   If lRetVal = NO_ERROR Then
      GetKeyValue = KeyValue
   Else
     ' MsgBox lRetVal & vbCrLf & KeyValue ' shfaq gabimin perkates
     GetKeyValue = vbNullString
   End If
   
End Function
```

_Komente:_ Sic verehet, jepet emri i celesit, emri i vleres se celesit, dhe variabli lRetVal na tregon nese vlera u lexua me sukses. Verejme se, nese celesi nuk ekziston, atehere vlera qe kthen funksioni eshte nje vlere e pacaktuar (NULL ne rastin e C/C++, ose vbNullString ne rastin e Visual Basic).


_Fshirja e nje celesi ne baze te emrit te dhene_



```
'4. Fshrija e nje celesi ne nje depo te caktuar
Public Sub DeleteKey(strKeyName As String, Optional lngPredefKey As Long)   
   Dim lRetVal As Long
   Dim hCurKey As Long
   
   ' Ne cilen depo?
   If lngPredefKey = 0& Then
      lngPredefKey = HKEY_CURRENT_USER
   End If
   
   ' referoju celesit me lRetVal
   ' Shenim: konstantja KEY_ALL_ACCESS eshte e nevojshme per privilegjet
   lRetVal = RegOpenKeyEx(lngPredefKey, strKeyName, 0&, KEY_ALL_ACCESS, hCurKey)

   ' gabim nese celesi me emrin e dhene nuk ekziston
   If lRetVal = ERROR_BADKEY Then
      If MsgBox("Celesi[" & strKeyName & "] nuk ekziston. Te krijohet? ", _
                  vbYesNo) = vbYes Then
         Call CreateKey(strKeyName, lngPredefKey)
      End If
      Exit Sub
   End If

   ' Tani fshi vleren, dhe gjyko mbi mesazhin e kthyer tek lRetVal:
   lRetVal = ShDeleteKey(lngPredefKey, strKeyName)
   
   If lRetVal <> NO_ERROR Then ' nese lRetVal eshte me gabim (pra jo zero):
      MsgBox lRetVal & vbCrLf & "Gabim, celesi nuk mund te fshihej:" & strKeyName
      Exit Sub
   Else
      ' mbyll referencen e krijuar, per te cliruar CPU:
      lRetVal = RegCloseKey(hCurKey)
      
      If lRetVal <> NO_ERROR Then MsgBox "Procedura e fshirjes nuk u perfundua me sukses."
   End If
   
End Sub
```

_Komente:_ Sic verehet, funksioni i mesiperm kontrollon nese celesi ekziston dhe e fshin ate nga depo e dhene.


*Disa Vrojtime Perfundimtare*

Shfrytezimi i regjistrit eshte nje nga mundesite me te vecanta qe i jepet programuesit. Ne kete menyre, programi i zhvilluar permban nje shkalle te larte serioziteti dhe rigoroziteti nga pikepamja e te koduarit ne menyre profesionale. Per me teper, ky lloj kodimi ka si avantazh kryesor shmangien e mbingarkeses qe do te ekzistonte nese konfigurimi do te kryhej nepermjet skedareve fizike (ne diskun e ngurte, le te themi). Me kete fryme, programuesi ka kontroll absolut mbi programin e zhvilluar, edhe pas kompilimit dhe prodhimit te tij, sepse ai mund te aksesoje celesat e krijuar nga programi sa here te doje (dhe per aq privilegje sa zoteron) duke hapur editorin e regjistrit. Theksojme faktin e privilegjit te perdoruesit aktual, sepse nje perdorues i zakonshem ne nje domain te caktuar nuk zoteron privilegje te mjaftueshme per te krijuar nje celes ne nje depo te ndryshme nga HKEY_CURRENT_USER.

Mbi te gjitha, fale shfrytezimit te regjistrit, mund te arrihet nje pafundesi kombinimesh, jo vetem per konfigurimin e programit, por edhe per mbrojtjen e tij, per preferencat e ndryshme te perdorueseve te ndryshem (duke krijuar, le te themi, nga nje celes per cdo perdorues), per te lexuar te dhena nga programe te tjera, qofte edhe nga sistemi operativ, etj.

----------

