الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

استشعار ربط الحاسوب بو حدات التخزين

بدأه محمد رضى في 30 يوليو 2009 · 0 رد · 745 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1

السلام عليكم و رحمة الله تعالى و بركاته,,

ملاحظة : بعيد البدإ في تحرير نص هذا الموضوع قمت بعملية بحث عما إذا كان أحد الأعضاء قد قام بكتابة موضوع مماثل. صحيح أنني وجدت بعض المواضيع المماثلة و لكن لا أحد منها به الشرح الكافي لفهم هذه التقنية. و للسادة المشرفين واسع النظر...

في هذه الموضوع سنتحدث عن وسيلة لاستشعار ربط المستخدم الحاسوب بوحدة تخزين من أي نوع سواء كانت قرص مرن, قرص صلب, وحدة تخزين من نوع usb أو ماشابه. فهم هذه التقنية سيمكننا من إضافة درجة أخرى من مرونة برامجنا في التعامل الأوتوماتيكي مع وحدات التخزين و التخفيف من الأسئلة الموجهة إلى المستخدم كمثيل : <<المرجو إدخال القرص X و الضغط على الزر OK>>.

أولا, يجب أن نتعرف على الرسالة WM_DEVICECHANGE التي يبعتها نظام التشغيل إلى كل النوافذ لإعلامها بتغيير في تكوين الأجهزة المرتبطة بالحاسوب. يعني أنه في كل مرة تم ربط الحاسوب بجهاز يقوم نظام الويندوز بإعلام كل النوافد بهذا الحدث عبر الرسالة WM_DEVICECHANGE.

ثانيا, يجب أن نتعرف عن نوع التغيير الذي طرأ و ما يهمنا هنا هو ربط جهاز بالحاسوب لاغير. ويمكننا معرفة ذلك بقراءة محتوى المتغير wParam للرسالة WM_DEVICECHANGE و الذي يجب أن يكون DBT_DEVICEARRIVAL. لمعرفة باقي الأحداث أنقر هنا.

ثالثا و أخيرا, معرفة إذا كان الجهاز وحدة تخزين أم أي جهاز آخر فالرسالة WM_DEVICECHANGE تبعث عند أي تغيير في تكوين الأجهزة المرتبطة بالحاسوب. و للتفريق بين وحدات التخزين و الأجهزة الأخرى, فإننا نقرأ محتوى المتغير dbcv_devicetype أحد أعضاء بنية البيانات DEV_BROADCAST_VOLUME حيث قراءة محتوى يعادل التابث DBT_DEVTYP_VOLUME يؤكد لنا أن الجهاز الذي تم ربطه للتو بالحاسوب هو وحدة تخزين و ليس أي نوع آخر من الأجهزة. المتغير lParam يحتوي على مؤشر نحو الذاكرة التي بها محتوى بنية البيانات DEV_BROADCAST_VOLUME الخاصة بهذا الحدث.

و بعد الكثير من الكلام النظري الذي يرهقني أنا شخصيا, لنبدأ في تطبيق ما تكلمنا عليه سابقا. فلنبدأ إذن بتعريف الثوابث التي تمكننا من التعرف على الرسالة و نوع و حداث التخزين :

		// رسالة إعلام بتغيير في مكونات الأجهزة
		private const uint WM_DEVICECHANGE = 0x219;
		// جهاز تم ربطه بالحاسوب
		private const uint DBT_DEVICEARRIVAL = 0x8000;
		// نوع الجهاز : وحدة تخزين
		private const uint DBT_DEVTYP_VOLUME = 0x00000002;

بعدها نعرف بنية البيانات DEV_BROADCAST_VOLUME التي سيضعها نظام التشغيل رهن إشارتنا

للتعرف على الجهاز الذي تم ربطه للتو بالحاسوب :

		// هذه بنية بيانات يرسلها النظام بها معلومات عن الجهاز الذي تم ربطه للتو
		private struct DEV_BROADCAST_VOLUME {
			// حجم البنية بالبايت
			public int dbcv_size;
			// نوع الجهاز
			public int dbcv_devicetype;
			public int dbcv_reserved;
			// قناع الوحدة المنطقية التي تم ربط الجهاز بها
			public int dbcv_unitmask;
			// أعلام للمعلومات الإضافية حول الجهاز
			public short dbcv_flags;
		};

بعدها تلزمنا وسيلة للتعرف على الرسالة WM_DEVICECHANGE عند بعثها من طرف نظام التشغيل. وفي حالتنا و نحن في منتدى C# نحتاج إلى تجاوز أو override الدالة WndProc للفورم الذي نريد أن يتم الإستشعار داخله. و لهذا نزيد نص الدالة التالية في آخر كلاس الفورم :

		protected override void WndProc(ref Message m)
		{
			// إذا كانت رسالة إعلام بتغيير في تكوين الأجهزة المرتبطة بالحاسوب
			if(m.Msg == WM_DEVICECHANGE) {
				// إذا كانت الرسالة تعلم بربط الجهاز...
				if((uint)m.WParam == DBT_DEVICEARRIVAL) {
					// قراءة معلومات الحدث
					DEV_BROADCAST_VOLUME dbv = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
					// إذا كان الجهاز الذي تم ربطه وحدة تخزين
					if(dbv.dbcv_devicetype == DBT_DEVTYP_VOLUME) {
						// الحصول على حرف وحدة التخزين التي تم ربطها
						char drvLetter = '\0';
						for(int i = 0; i < 32; i++) {
							if((dbv.dbcv_unitmask & (1 << i)) != 0) {
								drvLetter = (char)(i + (int)'A');
								break;
							}
						}
						// TODO +> زد هنا الكود المراد تشغيله عند ربط وحدة تخزين 

بالحاسوب
						DialogResult dr = MessageBox.Show("تم ربط الحاسب بوحدة تخزين 

جديدة...\nهل تريد تفحص المحتويات الجديدة؟", "وحدة تخزين جديدة...", 

MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
						if(dr == DialogResult.Yes) {
							Process.Start(drvLetter + @":\");
						}
					}
				}
			}
			base.WndProc(ref m);
		}

الكود في حالته هذه لا يقوم إلا بفتح مكتشف ويندوز على الوحدة المنطقية للجهاز الذي تم ربطه بالحاسوب ولكن الكود سهل للغاية بحيث يمكن لأي شخص وضع الكود المراد تنفيده عند الربط تحت التعليق //TODO +>

في الملف المرفق تجدون مشروع هذا الموضوع به كل الكود المذكور سالفا.

تحياتي...

WindowsFormsApplication4.rar

تم تعديل هذه المشاركة بواسطة محمد رضى في 30 يوليو 2009 في 18:00

مواضيع مشابهة