/// <summary> /// 当设备插入或拔出时请求接收消息 /// Requests to receive a notification when a device is attached or removed. /// </summary> /// <param name="devicePathName"> 设备句柄 handle to a device. </param> /// <param name="formHandle"> 接收事件的窗体句柄 handle to the window that will receive device events. </param> /// <param name="classGuid"> 设备接口 GUID device interface GUID. </param> /// <param name="deviceNotificationHandle"> 返回设备事件句柄 returned device notification handle. </param> /// <returns> /// 成功返回True /// </returns> public Boolean RegisterForDeviceNotifications(String devicePathName, IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle) { // A DEV_BROADCAST_DEVICEINTERFACE header holds information about the request. DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE(); IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero; Int32 size = 0; try { // Set the parameters in the DEV_BROADCAST_DEVICEINTERFACE structure. // Set the size. size = Marshal.SizeOf(devBroadcastDeviceInterface); devBroadcastDeviceInterface.dbcc_size = size; // Request to receive notifications about a class of devices. devBroadcastDeviceInterface.dbcc_devicetype = DeviceManagementDeclarations.DBT_DEVTYP_DEVICEINTERFACE; devBroadcastDeviceInterface.dbcc_reserved = 0; // Specify the interface class to receive notifications about. devBroadcastDeviceInterface.dbcc_classguid = classGuid; // Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure. devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size); // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer. // Set fDeleteOld True to prevent memory leaks. Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true); // 调用API函数 deviceNotificationHandle = DeviceManagementDeclarations.RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DeviceManagementDeclarations.DEVICE_NOTIFY_WINDOW_HANDLE); Debug.WriteLine("在函数RegisterForDeviceNotifications中" + this.MyDebugging.ResultOfAPICall("RegisterDeviceNotification")); // 从非管理的devBroadcastDeviceInterfaceBuffer数据块集合到受管理的devBroadcastDeviceInterface对象 // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to the managed object devBroadcastDeviceInterface Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface); if ((deviceNotificationHandle.ToInt32() == IntPtr.Zero.ToInt32())) { return(false); } else { return(true); } } catch (Exception ex) { throw; } finally { if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero) { // 释放由AllocHGlobal函数分配的内存空间。 Free the memory allocated previously by AllocHGlobal. Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer); } } }
/// <summary> /// Requests to stop receiving notification messages when a device in an /// interface class is attached or removed. /// </summary> /// <param name="deviceNotificationHandle"> handle returned previously by /// RegisterDeviceNotification. </param> public void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle) { try { // 调用API函数 DeviceManagementDeclarations.UnregisterDeviceNotification(deviceNotificationHandle); Debug.WriteLine("在函数StopReceivingDeviceNotifications中" + this.MyDebugging.ResultOfAPICall("UnregisterDeviceNotification")); } catch (Exception ex) { throw; } }
/// <summary> /// Use SetupDi API functions to retrieve the device path name of an /// attached device that belongs to a device interface class. /// </summary> /// <param name="myGuid"> an interface class GUID. </param> /// <param name="devicePathName"> a pointer to the device path name of an attached device. </param> /// <returns> True if a device is found, False if not</returns> public Boolean FindDeviceFromGuid(System.Guid myGuid, ref String[] devicePathName) { Int32 bufferSize = 0; IntPtr detailDataBuffer = IntPtr.Zero; Boolean deviceFound; IntPtr deviceInfoSet = new System.IntPtr(); Boolean lastDevice = false; Int32 memberIndex = 0; DeviceManagementDeclarations.SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new DeviceManagementDeclarations.SP_DEVICE_INTERFACE_DATA(); Boolean success; try { // 调用API 函数 deviceInfoSet = DeviceManagementDeclarations.SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DeviceManagementDeclarations.DIGCF_PRESENT | DeviceManagementDeclarations.DIGCF_DEVICEINTERFACE); Debug.WriteLine("在函数FindDeviceFromGuid中" + this.MyDebugging.ResultOfAPICall("SetupDiGetClassDevs")); deviceFound = false; memberIndex = 0; // The cbSize element of the MyDeviceInterfaceData structure must be set to // the structure's size in bytes. // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code. MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData); do { // Begin with 0 and increment through the device information set until no more devices are available. // 调用API函数 success = DeviceManagementDeclarations.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref MyDeviceInterfaceData); Debug.WriteLine("在函数FindDeviceFromGuid中" + this.MyDebugging.ResultOfAPICall("SetupDiEnumDeviceInterfaces")); // Find out if a device information set was retrieved. if (!success) { lastDevice = true; } else { // 调用API函数 success = DeviceManagementDeclarations.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero); Debug.WriteLine("在函数FindDeviceFromGuid中" + this.MyDebugging.ResultOfAPICall("SetupDiGetDeviceInterfaceDetail")); // 使用返回的缓冲区大小为SP_DEVICE_INTERFACE_DETAIL_DATA结构分配内存 detailDataBuffer = Marshal.AllocHGlobal(bufferSize); // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems. Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8); // 再次调用SetupDiGetDeviceInterfaceDetail 函数,这次传递一个指针给DetailDataBuffer,返回请求的缓冲区大小 success = DeviceManagementDeclarations.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero); Debug.WriteLine("在函数FindDeviceFromGuid中" + this.MyDebugging.ResultOfAPICall("SetupDiGetDeviceInterfaceDetail")); // 略过 cbsize (4 bytes) 以获得devicePathName的地址 IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4); // 获取devicePathName字符串. devicePathName[memberIndex] = Marshal.PtrToStringAuto(pDevicePathName); if (detailDataBuffer != IntPtr.Zero) { // 释放由 AllocHGlobal 分配的内存 Marshal.FreeHGlobal(detailDataBuffer); } deviceFound = true; } memberIndex++; }while (!((lastDevice == true))); return(deviceFound); } catch (Exception ex) { throw; } finally { // 调用API函数释放内存 if (deviceInfoSet != IntPtr.Zero) { DeviceManagementDeclarations.SetupDiDestroyDeviceInfoList(deviceInfoSet); Debug.WriteLine("在函数FindDeviceFromGuid中" + this.MyDebugging.ResultOfAPICall("SetupDiDestroyDeviceInfoList")); } } }