۱۳۸۸ تیر ۱۱, پنجشنبه

رجیستری

حتما شما هم تا حالا اسم رجیستری به گوشتون خورده و باهاش آشنایی دارید.
رجیستری ویندوز رو میشه از طریق برنامه ی regedit درش تغییراتی به وجود آورد.
همچنین یکسری توابع api نیز ویندوز داره که به وسیله ی اونا میتونین از داخل برنامه ی خودتون رجیستری رو تغییر بدید. 
حالا یک پروژه ی جدید باز کنید چون میخوایم در غالب یک پروژه قسمت عمده ی این توابع رو یادبگیریم(بگیرید چون من که بلدم (:   )
خب خیلی طبیعیه که برای کار کردن با یک رشته یا عدد از یک فایل دیگه اول اون رو باز کنیم.
برای این کار تابعی به نام RegOpenKeyEx وجود داره به شکل زیر

Public Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, ByRef phkResult As Long) As Long

اگر برنامه ی regedit رو باز کنید میبینید که وقتی اولین شاخه یعنی شاخه ی MyComputer رو باز میکنید پنج فولدر مشاهده میکنید.(از این به بعد به این فولدر ها میگیم key یا "کی" که به فارسی یعنی کلید.پس میگیم کلید ،فولدر تو رجیستری=کلید)
خب اگر در APIViewer خود در لیست ثابت ها(constants) نگاه کنید میبینید هشت کلید با نام کلید های ذکر شده وجود دارد که با سه تا از اونا کاری نداریم.
بقیه یه اونها به شرح زیر
Public Const HKEY_CLASSES_ROOT As Long = &H80000000
Public Const HKEY_CURRENT_CONFIG As Long = &H80000005
Public Const HKEY_CURRENT_USER As Long = &H80000001
Public Const HKEY_LOCAL_MACHINE As Long = &H80000002
Public Const HKEY_USERS As Long = &H80000003

قبل از اینکه سراغ کد نویسی برم این رو هم بگم که اگر مقدار برگشتی هرکدوم از توابع API مربوت به رجیستری مقدار 0 رو برگردونن یعنی تابع کارش رو با موفقیت به انجام رسونده و در غیر این صورت یعنی خطایی رخ داده.
خب بریم که یک کلید رو باز کنیم.
دونه دونه مقادیری رو که برای regopenkeyex نیاز دارید در پایین توزیح میدم
hKey=یکی از همون پنج ثابت
lpSubKey=نام کلیدی که میخواهیم اون رو باز کنیم
ulOptions=فقت یک صفر بزارید
samDesired=یک پوشش امنیتی که  یه چندتا ثابت میخواد به شرح زیر.
Public Const KEY_ALL_ACCESS As Long = ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))
Public Const STANDARD_RIGHTS_ALL As Long = &H1F0000
Public Const KEY_QUERY_VALUE As Long = &H1
Public Const KEY_SET_VALUE As Long = &H2
Public Const KEY_CREATE_SUB_KEY As Long = &H4
Public Const KEY_ENUMERATE_SUB_KEYS As Long = &H8
Public Const KEY_NOTIFY As Long = &H10
Public Const KEY_CREATE_LINK As Long = &H20
Public Const SYNCHRONIZE As Long = &H100000

شما فقت KEY_ALL_ACCESS رو مینیویسید ولی  ثابت های دیگر رو هم باید  توی ماژول یا جای دیگه نوشته باشید.
 و اگر نگاه کنید تمامی ثوابت توی خود  KEY_ALL_ACCESS  هستند پس  فقت کافیه KEY_ALL_ACCESS رو حفظ کنید.
و اینکی KEY_ALL_ACCESS باید بعد از ثوابط دیگر تعریف شود
phkResult=هندل کلیدی رو که باز کردیم بر میگرداند.
حالا برید تو رویداد Form1_Load و کد زیر رو بنویسید
Private Sub Form_Load()
Dim RetVal As Long
Dim SubKey As String
Dim KeyHandle As Long
SubKey = "console"
RetVal = RegOpenKeyEx(HKEY_CURRENT_USER, SubKey, 0, KEY_ALL_ACCESS, KeyHandle)
If Not RetVal = 0 Then
  MsgBox "error in openning"
  End
Else
  MsgBox "openning succeded"
  End
End If
End Sub

برنامه اول سأی میکنه که کلید console که در Hkey_Current_User هست رو باز کنه و اگه موفق شد هندل اون رو در متغیر KeyHandle قرار میده . ولی اگه با خطا مواجه شد اول میگه که در بازکردن مشکل به وجود آمده و بعد برنامه رو میبنده.
اگر هم که با خطا مواجه نشد  میگه که باز شدن با موفقیت انجام شد و بعد برنامه رو میبنده.
نکته:وقتی که یک کلید رجیستری رو باز میکنید یه مقداری رم رو به خودش اختصاص میده به همین علت وقتی یک کلید رجیستری باز شد و خوانده شد یا  تغییراتی درش به وجود آمد بای سریع بسته شه که رم رو  آزاد کنه .بستن  یک کلید رجیستری به وسیله ی یک API یه  دیگه انجام میشه ولی چون هنوز اون رو نخوندیم برنامه رو میبندیم و باز هم رم به این ترتیب آزاد میشه.
خب حالا میخوایم یک  مقدار(value) رو بخونیم.مقادیر رو در قسمت سمت راست  برنامه ی regedit مشاهده میکنید که متنها و عدد ها در انها ذخیره میشوند.
برای خواندن یک مقدار از تابع RegQueryValueEx استفاده میکنیم به شکل زیر.
 

Public Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, ByRef lpType As Long, ByRef lpData As Any, ByRef lpcbData As Long) As Long
خب حالا به به شرح آرگومان هاش میپردازیم
hKey=هندل کلید باز شده به وسیله ی RegOpenKeyEx
lpValueName=نام مقداری(value)ای که میخواهیم اونو باز کنیم
lpReserved=صفر
lpType=تایپ مقداری که میخواهیم باز کنیم که یه چندتا ثابت با پیشوند REG داره
Public Const REG_BINARY As Long = 3
Public Const REG_DWORD As Long = 4
Public Const REG_SZ As Long = 1
البته تایپ های دیگری هم وجود داره ولی اینا مهمترین هان
REG_SZ=مقادیر رشته ای
REG_BINARY=مقادیر دودویی
REG_DWORD=مقادیر Hex یا decimal
بقیه یه آرگومان 
lpData=متغیری که مقدار برگشتی به آن فرستاده میشود
lpcbData=طول مقدار برگشتی
خب دو آرگومان آخر یکم توضیح میخوان
برای بدست آوردن مقدار دو راه وجود دارد که من به این روش عمل میکنم
اول دو متغیر از نوع استرینگ(string) تعریف میکنیم
حد اکثر طول یکی از آنها رو مساوی با 255 قرار میدیم به شکل زیر
Dim Buff As String *255
Dim RegValue as String
بعد برای lpData متغیر اولی رو مینویسیم
برای lpcbData هم حد اکثر طول متغیر اولی رو مینویسیم
گیج نشید الان مثال میزنم متوجه میشید.
Private Sub Form_Load()
Dim RetVal As Long
Dim Buff As String * 255, Fn As String
RetVal = RegQueryValueEx(KeyHandle, ValueName, 0,  REG_SZ, ByVal Buff, 255)
If RetVal = 0 Then
  Fn = Left(Buff, 255)
Else
  MsgBox "error in reading", vbCritical, "error"
  End
End If
End Sub
بعد با دستور RegCloseKey باید کلید بسته بشه
بستن کلید خیلی سادس.فقط هندل کلیدی رو که باز کردین بهش بدین


Input Output

خب خیلی جاها من دیدم که گفتن نمیشه با ویژوال بیسیک ورودی خروجی هارو کنترل کرد. در صورتی که این حرف کاملآ اشتباه هست. ویژوال بیسیک قابلیت کنت...