PDA

View Full Version : خواندن تمام کلید های string در رجیستری



A_Salimi
شنبه 24 فروردین 1387, 17:38 عصر
با سلام

میخواستم بدونم چطور میتونم تمام کلید های string در یک شاخه خاص از رجیستری رو بخونم ؟ یعنی در حقیقت مشکلم اینه :

فرض کنیم شاخه ای با این آدرس داریم :


HKEY_CURRENT_USER/Software/MyKey

حالا فرض رو بر این میگیریم که تمام کلیدهای موجود در این زیر کلید از نوع رشته ای هستند ، اگر بخواهیم تمام کلیدها رو بخونیم بایستی از تابع QueryStringValue استفاده کنیم و مثلا از حلقه for استفاده کنم، اما در این تابع اولین پارامتر اسم زیر کلیدی هست که قراره خونده بشه . این اسم رو برای هر زیر کلید چطور و با چه تابعی دریافت کنم ؟

در ضمن اگه فرضی رو که در بالا گرفتیم رو نقض کنم (یعنی در کلید ساخته شده علاوه بر زیر کلید های string ، زیر کلیدهای دیگری مثل DWORD هم وجود داشته باشد ) و قصد داشته باشیم فقط مقادیر string رو بشماریم باید چیکار کنیم ؟ (یعنی چطور میشه فقط تعداد نوع خاصی از یک کلید رو شمرد ؟)

با تشکر

Nima_NF
یک شنبه 25 فروردین 1387, 15:27 عصر
از تابع EnumKey برای شمارش و دریافت subkey ها می توانید استفاده کنید.

اگر از QueryValue استفاده کنید در یکی از پارامتر ها می توانید نوع داده ای را نیز دریافت کنید.

A_Salimi
یک شنبه 25 فروردین 1387, 18:00 عصر
اگه به خاطر داشته باشید قبلا هم یکبار در مورد تابع EnumKey بحث کردیم اما من توی پارامتر سوم این تابع مشکل دارم و مشکل شمردن کلید ها رو اونجا با روشی برطرف کردم .
این چیزی است که در msdnدر مورد پارامتر سوم این تابع آمده :

pnNameLength

اشاره گری به یک متغیر که سایز را به TCHAR مشخص میکند .سایز بافر مشخص شده با پارامتر pszName .این سایز باید شامل کاراکتر به NULL ختم شده باشد . هنگامی که متد بازگشت میشود ، متغیر اشاره شده با pnNameLength شامل تعداد کاراکترهای ذخیره شده در بافر میشود. . .

من اینطوری از این تابع استفاده میکنم :



int i=0;
TCHAR subname[MAX_KEY_LENGTH];
DWORD namelen=MAX_KEY_LENGTH;
while(LONG retCode=m_cKey.EnumKey(i,subname,&namelen,NULL)!=ERROR_NO_MORE_ITEMS){
if (retCode == ERROR_SUCCESS)
{
_tprintf(TEXT("(%d) %s\n"), i+1, subname);
}
}


که البته واقعیتش اینه که در شرط if متوجه نیستم دقیقا چی اتفاق میفته و فقط از msdn کپی کردم:لبخند:

اما کاری رو که من میخوام انجام بدم اینه :

قصد دارم یک لیست درست کنم با یک دکمه Add و یک کادر ویرایش . . . میخوام زمانی که کاربر دکمه Add رو کلیک میکنه یک کلید در رجیستری با مقدار رشته ای ایجاد شه و متن درون کادر ویرایش در اون ذخیره بشه
الگوریتمی رو که من پیاده کردم اینطوری بود : یک کلید رشته ای با نام خاصی رو ایجاد میکردم و در اون یک عدد رو به صورت رشته ای ذخیره میکردم و بعدش در هر بار کلیک کاربر این کارها رو میکردم :
1-اون عددی رو که به صورت رشته ای بود رو از کلید میخوندم .
2- با این مقدار رشته ای یک کلید میساختم و رشته کادر ویرایش رو در اون ذخیره میکردم.
3-عدد رشته ای رو به عدد integer تبدیل میکردم.
4-به عدد حاصل یکی اضافه میکردم.
5-عدد رو دوباره به رشته تبدیل میکردم.
6-رشته جدید رو در همون کلید اصلی که گفتم ذخیره میکردم.
پس در حقیقت مشکل نام و شمردن کلیدها برطرف میشد اما یکی از مشکلاتی که برای من بوجود آمد سوال اول پست قبل من بود چرا که من قصد داشتم در هر بار اجرای برنامه تمام مقادیر رشته ای کلیدها در لیست نمایش داده شوند که لازم بود من نام کلیدها رو میدانستم . . . شاید شما بگید که نام کلیدها همان اعداد رشته ای هستند اما مطمئنا با بزرگ شدن برنامه به مشکلاتی مثل حذف شدن یک کلید و . . . روبرو میشدم .
سوالم رو در یک خط دوباره میگم :
چطور میشه تمام کلیدهای رشته ای رو خوند و اونها رو در یک لیست نمایش داد ؟:متفکر:

Nima_NF
یک شنبه 25 فروردین 1387, 22:29 عصر
چطور میشه تمام کلیدهای رشته ای رو خوند و اونها رو در یک لیست نمایش داد ؟
می توانید از RegEnumValue همانند EnumKey استفاده کنید و در هر مرحله از حلقه مقدار خروجی lpType را با نوع رشته ای از صفه زیر مقایسه کنید:
http://msdn2.microsoft.com/en-us/library/ms724884(VS.85).aspx (http://msdn2.microsoft.com/en-us/library/ms724884%28VS.85%29.aspx)

مثلا اگر نوع داده ای رشته ای بود می توانید محتویات آن را در لیست کپی کنید و...


که البته واقعیتش اینه که در شرط if متوجه نیستم دقیقا چی اتفاق میفته و فقط از msdn کپی کردم
در هر مرحله باید شماره index یک واحد افزایش بیابد تا همه کلید ها به ترتیب بررسی و اطلاعاتشان دریافت شود، در همین قسمت عمل کپی کردن در لیست می تواند انجام گیرد. (در قطعه کدی که قرار دادید کار خواصی انجام نمی شود ،فقط نام و شماره ایندکس کلید در خروجی کنسول چاپ می شود)

A_Salimi
دوشنبه 26 فروردین 1387, 11:35 صبح
چند تا سوال دارم :

1-اون طوری که من بررسی کردم مشکلی که پیش میاد اینه که تابع EnumKey در برنامه من بعد از ایندکس صفر مقدار ERROR_NO_MORE_ITEMS رو بر میگردونه که این یعنی No more data is available . خوب پس نتیجه ای که میگیریم اینه که تابع نمی تونه کلید های بیشتری رو بررسی کنه و این یعنی که احتمالا اون زیر کلید باز نشده . . . ولی همونطوری که گفتم من در اون کلید زیر کلیدهایی رو ایجاد میکنم و هر کلیدی رو که بخوام رو میخونم پس این نظریه رد شده است . حالا سوالم اینه : مگه وقتی یک کلید ایجاد میشه (و در سازنده کلاس باز میشه ) همه زیر کلیدها در دسترس نیستند ؟
2-عبارت throw( ); که در آخر این تابع اومده یعنی چی ؟ و آیا در برنامه هم باید ذکر بشه ؟
3-پارامتر آخر( pftLastWriteTime) که null هست آیا به مشکل ایجاد شده مربوط نمیشه ؟
4- یک سوال (نه زیاد مربوط به بحث) :در بعضی از توابع پارامتر هایی وجود دارند که مثلا گفته شده :این پارامتر باید حتما NULL باشد . اگه باید اون پارامتر NULL باشه اصلا چرا اون رو برای تابع تعریف میکنن ؟

Nima_NF
دوشنبه 26 فروردین 1387, 17:49 عصر
حالا سوالم اینه : مگه وقتی یک کلید ایجاد میشه (و در سازنده کلاس باز میشه ) همه زیر کلیدها در دسترس نیستند ؟مشکل باید در باز نشدن درست کلید باشد که باید بررسی کنید که چه اشتباهی در مراحل قبل انجام داده اید. زیر کلید ها در دسترس هستند.


2-عبارت throw( ); که در آخر این تابع اومده یعنی چی ؟ و آیا در برنامه هم باید ذکر بشه ؟این کار خواصی نیست و نیازی نیست وارد جزییات آن شوید. فقط بدانید که در انتها throw فقط معلوم می کند که تابع مورد نظر استثنایی را ارسال نمی کند (برای پردازش خطاهای C)؛


3-پارامتر آخر( pftLastWriteTime) که null هست آیا به مشکل ایجاد شده مربوط نمیشه ؟پارامتر آخر فقط برای این هست که اگر غیر NULL باشد آخرین زمان شمارش زیر کلید ها را برمیگرداند. (که بهتر هست متغیری جای NULL باشد) اما در هر حال چیز ضروری نیست.



4- یک سوال (نه زیاد مربوط به بحث) :در بعضی از توابع پارامتر هایی وجود دارند که مثلا گفته شده :این پارامتر باید حتما NULL باشد . اگه باید اون پارامتر NULL باشه اصلا چرا اون رو برای تابع تعریف میکنن ؟
در مورد این تابع NULL ضروری نیست، فقط اگر آخرین پارامتر را فراخوانی نکنید خودش NULL کی گذارد.

اما در توابع دیگر که NULL ضروری هست به چند دلیل می باشد:
برای سازگاری با نسخه های قبلی این تابع در ویندوز های سری های قبل و یا حتی سیستم عامل های 16 بیتی قدیمی تر.
و یا برای رزرو کردن آن پارامتر برای آینده تا فرمت تابع حفظ شود و بتوان به راحتی قابلیت های جدید را از طریق آن پارامتر در آن اضافه کرد.

A_Salimi
سه شنبه 27 فروردین 1387, 00:24 صبح
با تشکر از پاسخهای شما

من برنامه رو در زیر قرار میدم .لطفا اشکالات من رو در کد نویسی بگید و در شرط if کد مناسب رو قرار بدید.
برنامه به محض اجرا کلید های مورد نظر را ایجاد خواهد کرد .

Nima_NF
سه شنبه 27 فروردین 1387, 02:45 صبح
1) برای دریافت کلید ها یا زیرکلید ها باید از EnumKey استفاده کنید (MyKey یک کلید هست)، مواردی که نام آن ها را که key1 , key2 , key3 نام گذاشته اید کلید نیستند ، نام مقدار یا نام value هستند نه کلید و داده های جلوی آن ها همان data هست.

پس برای گرفتن و شمارش مقادیر باید از RegEnumValue استفاده کنید نه EnumKey
(تابع فوق نیز در پست دوم معرفی شد)

2) وقتی کلید را می سازید یا باز می کنید در آرگومان اول باید یکی از هندل ها باشد نه اسم خوودش مانند HKEY_LOCAL_MACHINE و سایر کلید های اصلی پیش فرض.

3) برای مقایسه هر دو تابع شمارشی RegEnumValue و EnumKey باید از ERROR_SUCCESS استفاده کنید نه ERROR_NO_MORE_ITEMS

4) تابع RegEnumValue در یکی از پارامتر هایش (با متغیر dwType استفاده کرده ام) نوع داده ای value را برمی گرداند که با یک If ساده می توانید فقط رشته ها را در خروجی بریزید.
(لینک انواع نیز در پست دوم معرفی شد)

5) همیشه قبل از هر کاری کلید را با open باز کنید، چون استفاده create در سازنده کلاس درست هست که آن را باز می کند اما اشتباه هست و هر وقت برنامه اجرا می شود کلید ها دوباره ساخته می شوند که برای دفعات بعد لزومی ندارد.

6) از TCHAR برای QueryStringValue استفاده کنید تا اندازه رشته مشخص باشد و سپس در لیست باکس بریزید.

7) برنامه را به طور کامل در OnBnClickedOk و سازنده کلاس ویرایش کردم که می توانید مطالعه کنید.

8 ) پایان !

xxxsenatorxxx
سه شنبه 13 تیر 1391, 01:01 صبح
سلام
من میخوام تمام زیر شاخه های این شاخم رو بخونه و برگردونه نه مقدار های اون شاخه رو.کجای کد زیر رو تغییر بدم؟
RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\");
String[] stTemp = rk.GetValueNames();
foreach (string st in stTemp)
textBox1.AppendText(rk.GetValue(st).ToString() + "\n");