- سيكون هذا الموضوع عبارة عن مشروع عمل جماعي يشترك فيه الجميع وسأضع الهيكل المبدئي فقط وأرجو أن يقوم أعضاء المنتدى جميعا بالمشاركة بالتطوير
- أرجو من الجميع المشاركة بالأفكار والأكواد لتطوير الفئة هنا إلى أفضل شكل ممكن بكافة الامكانيات الممكن تخيلها
فكرة العمل: بناء فئة Class للتعامل مع الأقراص القابلة للإزالة والتي يتم توصيلها إلى الحاسب عبر منفذ USB
الفوائد: مثال على البرمجة غرضية التوجه، بناء الفئات، إضافة الخصائص، إطلاق الأحداث
أرجو قراءة الموضوع Windows Management Instrumentation للأخ حزووم فهو يشكل فائدة في التعرف على بعض الأشياء المتعلقة بالأكواد المطروحة هنا وفي فهم كيفية عملها
كما أرجو قراءة موضوعي معلومة: كيف تستطيع إطلاق أحداثك الخاصة حتى تكون لديك فكرة عن كيفية إطلاق الأحداث من داخل فئتنا
سنقوم أولا بتعريف فئة Class لتضم عملنا وعندما ننتهي منها يجب أن تضم العديد من الخصائص والاجراءات المفيدة
Public Class UsbDriveDetect End Class
سنحتاج لإضافة مرجع لـ ManagementEventWatcher حتى نستطيع مراقبة ما يحدث داخل الجهاز والذي يقوم بمراقبة الأحداث المنطلقة بناء على استعلام معين و سنستخدم الكلمة WithEvents في التعريف حتى نستطيع تعقب الأحداث الصادرة عنه
Private WithEvents m_MediaConnectWatcher As ManagementEventWatcher
ولكي يعمل بشكل صحيح سنحتاج لإضافة مرجع لـ System.Management
قم بإضافة System.Management من قائمة Project بند Add Reference ثم استخدم الاستيراد التالي قبل كل شئ في الملف وحتى قبل تعريف الفئة أيضا
Imports System.Management
سنحتاج أيضا لبناء مشيد الفئة Sub New الذي سيضبط التهيئة الأساسية لفئتنا والذي سنقوم من خلاله بضبط خصائص ManagementEventWatcher الذي يقوم بالعمل لأجلنا
Sub New()
Dim Query2 As New WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 1 " _
& "WHERE TargetInstance ISA 'Win32_DiskDrive'")
Me.m_MediaConnectWatcher = New ManagementEventWatcher
Me.m_MediaConnectWatcher.Query = Query2
End Subسنقوم الآن بوضع إجراءات لبدء وإيقاف تعقب وضع وإزالة أقراص USB
Public Sub StartDetection() Me.m_MediaConnectWatcher.Start() End Sub Public Sub StopDetection() Me.m_MediaConnectWatcher.Stop() End Sub
نريد الآن اعلام مستخدم فئتنا عن طريق إطلاق حدث خاص عندما يتم وضع أو إزالة قرص عن طريق منفذ USB في الجهاز سنقوم بإنشاء فئة مشتقة من System.EventArgs و ذلك كفئة فرعية ضمن فئتنا الأساسية UsbDriveDetect حتى نستخدمها لإطلاق حدثنا
ولكن سنحتاج أولا للتعريف التالي لإعادة حالة القرص هل تم وضعه أو إزالته ضع التعريف التالي بعد بداية تعريف الفئة
Public Enum EnUsbArrivedRemoved Arrived Removed End Enum
وفيما يلي نص الفئة الخاصة بالحدث
Public Class UsbDriveEeventArgs Inherits System.EventArgs Private m_DeviceName As String Private m_DriveLetter As String Private m_ArrivedRemoved As EnUsbArrivedRemoved Sub New(ByVal DeviceName As String, ByVal DriveLetter As String, ByVal ArrivedRemoved As EnUsbArrivedRemoved) Me.m_DeviceName = DeviceName Me.m_DriveLetter = DriveLetter Me.m_ArrivedRemoved = ArrivedRemoved End Sub Public ReadOnly Property DeviceName() As String Get Return Me.m_DeviceName End Get End Property Public ReadOnly Property DriveLetter() As String Get Return Me.m_DriveLetter End Get End Property Public ReadOnly Property ArrivedRemoved() As EnUsbArrivedRemoved Get Return Me.m_ArrivedRemoved End Get End Property End Class
و أيضا بعد بداية تعريف الفئة ضع السطر التالي الذي سيعرف الحدث الذي سنقوم بإطلاقه
Public Event UsbDeviceArrivedRemoved(ByVal sender As Object, ByVal e As UsbDriveEeventArgs)
قبل استخدام الحدث UsbDeviceArrivedRemoved لإعلام المستخدم بوضع أو إزالة قرص USB يجب الحصول على حرف ذلك القرص
Private Function GetDriveLetterFromDisk(ByVal Name As String) As String
Dim oq_part, oq_disk As ObjectQuery
Dim mos_part, mos_disk As ManagementObjectSearcher
Dim obj_part, obj_disk As ManagementObject
Dim ans As String = ""
' WMI queries use the "\" as an escape charcter
Name = Replace(Name, "\", "\\")
' First we map the Win32_DiskDrive instance with the association called
' Win32_DiskDriveToDiskPartition. Then we map the Win23_DiskPartion
' instance with the assocation called Win32_LogicalDiskToPartition
oq_part = New ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & Name & """} WHERE AssocClass =
Win32_DiskDriveToDiskPartition")
mos_part = New ManagementObjectSearcher(oq_part)
For Each obj_part In mos_part.Get()
oq_disk = New ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & obj_part("DeviceID") & """} WHERE AssocClass =
Win32_LogicalDiskToPartition")
mos_disk = New ManagementObjectSearcher(oq_disk)
For Each obj_disk In mos_disk.Get()
ans &= obj_disk("Name") & ","
Next
Next
Return ans.Trim(","c)
End Functionحيث نمرر له اسم الجهاز الذي تم الكشف عن إضافته وهو يعيد لنا حرف السواقة المرتبطة به وذلك باستخدم ManagementObjectSearcher للحصول عليه حيث ستلاحظ أن طريقة الاستعلام هنا مشابهة لاستعلامات قواعد البيانات ولكنها هنا على فئات WMI بدلا من جداول قاعدة البيانات
Private Function GetDriveLetterFromDisk(ByVal Name As String) As String
Dim oq_part, oq_disk As ObjectQuery
Dim mos_part, mos_disk As ManagementObjectSearcher
Dim obj_part, obj_disk As ManagementObject
Dim ans As String = ""
' WMI queries use the "\" as an escape charcter
Name = Replace(Name, "\", "\\")
' First we map the Win32_DiskDrive instance with the association called
' Win32_DiskDriveToDiskPartition. Then we map the Win23_DiskPartion
' instance with the assocation called Win32_LogicalDiskToPartition
oq_part = New ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & Name & """} WHERE AssocClass =
Win32_DiskDriveToDiskPartition")
mos_part = New ManagementObjectSearcher(oq_part)
For Each obj_part In mos_part.Get()
oq_disk = New ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & obj_part("DeviceID") & """} WHERE AssocClass =
Win32_LogicalDiskToPartition")
mos_disk = New ManagementObjectSearcher(oq_disk)
For Each obj_disk In mos_disk.Get()
ans &= obj_disk("Name") & ","
Next
Next
Return ans.Trim(","c)
End Functionوالآن سنتتبع الحدث EventArrived الخاص بـ ManagementEventWatcher حتى نعرف متى تم وضع أو إزالة قرص USB وذلك كي نستطيع اطلاق حدثنا المناسب وفقا للحدث المستقبل
Private Sub m_MediaConnectWatcher_EventArrived(ByVal sender As Object, ByVal e As System.Management.EventArrivedEventArgs) Handles
m_MediaConnectWatcher.EventArrived
Dim mbo, obj As ManagementBaseObject
' the first thing we have to do is figure out if this is a creation or deletion event
mbo = CType(e.NewEvent, ManagementBaseObject)
' next we need a copy of the instance that was either created or deleted
obj = CType(mbo("TargetInstance"), ManagementBaseObject)
If obj("InterfaceType") = "USB" Then
Select Case mbo.ClassPath.ClassName
Case "__InstanceCreationEvent"
Dim Ee As New UsbDriveEeventArgs(obj("Caption"), GetDriveLetterFromDisk(obj("Name")), EnUsbArrivedRemoved.Arrived)
RaiseEvent UsbDeviceArrivedRemoved(Me, Ee)
Case "__InstanceDeletionEvent"
Dim Ee As New UsbDriveEeventArgs(obj("Caption"), "", EnUsbArrivedRemoved.Removed)
RaiseEvent UsbDeviceArrivedRemoved(Me, Ee)
End Select
End If
End Subوبهذا نكون وصلنا للفئة الأساسية التي سنقوم بتطويرها معا وفيما يلي سرد كامل لكود هذه الفئة حتى النقطة التي وصلت إليها الآن
Imports System.Management
Public Class UsbDriveDetect
Private WithEvents m_MediaConnectWatcher As ManagementEventWatcher
Public Enum EnUsbArrivedRemoved
Arrived
Removed
End Enum
Public Event UsbDeviceArrivedRemoved(ByVal sender As Object, ByVal e As UsbDriveEeventArgs)
Sub New()
Dim Query2 As New WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 1 " _
& "WHERE TargetInstance ISA 'Win32_DiskDrive'")
Me.m_MediaConnectWatcher = New ManagementEventWatcher
Me.m_MediaConnectWatcher.Query = Query2
End Sub
Public Sub StartDetection()
Me.m_MediaConnectWatcher.Start()
End Sub
Public Sub StopDetection()
Me.m_MediaConnectWatcher.Stop()
End Sub
Private Function GetDriveLetterFromDisk(ByVal Name As String) As String
Dim oq_part, oq_disk As ObjectQuery
Dim mos_part, mos_disk As ManagementObjectSearcher
Dim obj_part, obj_disk As ManagementObject
Dim ans As String = ""
' WMI queries use the "\" as an escape charcter
Name = Replace(Name, "\", "\\")
' First we map the Win32_DiskDrive instance with the association called
' Win32_DiskDriveToDiskPartition. Then we map the Win23_DiskPartion
' instance with the assocation called Win32_LogicalDiskToPartition
oq_part = New ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & Name & """} WHERE AssocClass =
Win32_DiskDriveToDiskPartition")
mos_part = New ManagementObjectSearcher(oq_part)
For Each obj_part In mos_part.Get()
oq_disk = New ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & obj_part("DeviceID") & """} WHERE AssocClass =
Win32_LogicalDiskToPartition")
mos_disk = New ManagementObjectSearcher(oq_disk)
For Each obj_disk In mos_disk.Get()
ans &= obj_disk("Name") & ","
Next
Next
Return ans.Trim(","c)
End Function
Public Class UsbDriveEeventArgs
Inherits System.EventArgs
Private m_DeviceName As String
Private m_DriveLetter As String
Private m_ArrivedRemoved As EnUsbArrivedRemoved
Sub New(ByVal DeviceName As String, ByVal DriveLetter As String, ByVal ArrivedRemoved As EnUsbArrivedRemoved)
Me.m_DeviceName = DeviceName
Me.m_DriveLetter = DriveLetter
Me.m_ArrivedRemoved = ArrivedRemoved
End Sub
Public ReadOnly Property DeviceName() As String
Get
Return Me.m_DeviceName
End Get
End Property
Public ReadOnly Property DriveLetter() As String
Get
Return Me.m_DriveLetter
End Get
End Property
Public ReadOnly Property ArrivedRemoved() As EnUsbArrivedRemoved
Get
Return Me.m_ArrivedRemoved
End Get
End Property
End Class
Private Sub m_MediaConnectWatcher_EventArrived(ByVal sender As Object, ByVal e As System.Management.EventArrivedEventArgs) Handles
m_MediaConnectWatcher.EventArrived
Dim mbo, obj As ManagementBaseObject
' the first thing we have to do is figure out if this is a creation or deletion event
mbo = CType(e.NewEvent, ManagementBaseObject)
' next we need a copy of the instance that was either created or deleted
obj = CType(mbo("TargetInstance"), ManagementBaseObject)
If obj("InterfaceType") = "USB" Then
Select Case mbo.ClassPath.ClassName
Case "__InstanceCreationEvent"
Dim Ee As New UsbDriveEeventArgs(obj("Caption"), GetDriveLetterFromDisk(obj("Name")), EnUsbArrivedRemoved.Arrived)
RaiseEvent UsbDeviceArrivedRemoved(Me, Ee)
Case "__InstanceDeletionEvent"
Dim Ee As New UsbDriveEeventArgs(obj("Caption"), "", EnUsbArrivedRemoved.Removed)
RaiseEvent UsbDeviceArrivedRemoved(Me, Ee)
End Select
End If
End Sub
End Classويمكنكم تجربة استخدامه ضمن برنامج كالتالي
عرف متغيرا عاما يشير إلى فئتنا ضمن فئة النموذج
Private WithEvents UsbMonitor As New UsbDriveDetect
أضف زري أوامر لبدء وإيقاف التعقب
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.UsbMonitor.StartDetection() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.UsbMonitor.StopDetection() End Sub
عالج الحدث الصادر عن فئتنا إظهار رسالة مثلا
Private Sub UsbMonitor_UsbDeviceArrivedRemoved(ByVal sender As Object, ByVal e As UsbDriveDetect.UsbDriveEeventArgs) Handles UsbMonitor.UsbDeviceArrivedRemoved MsgBox(e.DeviceName & ControlChars.CrLf & e.DriveLetter & ControlChars.CrLf & e.ArrivedRemoved.ToString) End Sub



