als_Latn slv_Latn bos_Latn
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)
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).
Kodi:
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
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
Kodi:
' 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
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.
Kodi:
' 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
Leximi i nje vlere ne nje celes te dhene
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).
Kodi:
' 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
Fshirja e nje celesi ne baze te emrit te dhene
Komente: Sic verehet, funksioni i mesiperm kontrollon nese celesi ekziston dhe e fshin ate nga depo e dhene.
Kodi:
'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
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.
als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn als_Latn nya_Latn eng_Latn als_Latn als_Latn eng_Latn als_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn oci_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn als_Latn als_Latn eng_Latn tpi_Latn als_Latn eng_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn als_Latn cat_Latn nya_Latn pap_Latn eng_Latn als_Latn als_Latn als_Latn als_Latn als_Latn eng_Latn eng_Latn eng_Latn eng_Latn als_Latn hne_Deva eng_Latn eng_Latn als_Latn eng_Latn als_Latn ron_Latn als_Latn als_Latn als_Latn nya_Latn glg_Latn eng_Latn tpi_Latn als_Latn als_Latn als_Latn afr_Latn eng_Latn eng_Latn tpi_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn hne_Deva als_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn ron_Latn eng_Latn als_Latn als_Latn hun_Latn lim_Latn nno_Latn afr_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn als_Latn eng_Latn ron_Latn als_Latn als_Latn nya_Latn zul_Latn eng_Latn als_Latn als_Latn tpi_Latn eng_Latn eng_Latn tpi_Latn tpi_Latn eng_Latn eng_Latn eng_Latn tpi_Latn als_Latn hne_Deva als_Latn als_Latn eng_Latn hne_Deva eng_Latn eng_Latn als_Latn als_Latn hne_Deva eng_Latn eng_Latn nno_Latn hne_Deva eng_Latn afr_Latn tpi_Latn eng_Latn eng_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn eng_Latn hne_Deva hne_Deva eng_Latn eng_Latn als_Latn als_Latn nya_Latn als_Latn eng_Latn tpi_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn cat_Latn als_Latn eng_Latn als_Latn eng_Latn als_Latn eng_Latn eng_Latn eng_Latn ron_Latn eng_Latn als_Latn hun_Latn als_Latn als_Latn ron_Latn eng_Latn als_Latn eng_Latn als_Latn eng_Latn ron_Latn als_Latn als_Latn als_Latn