我试图从USB设备上捕获VIP和PID:
public const int WM_DEVICECHANGE = 0x219;
public const int DBT_DEVTYP_VOLUME = 0x00000002;
public const int DBT_DEVICEARRIVAL = 0x8000;
[StructLayout(LayoutKind.Sequential)]
internal class DEV_BROADCAST_HDR
{
public int dbch_size;
public int dbch_devicetype;
public int dbch_reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DEV_BROADCAST_DEVICEINTERFACE
{
public int dbcc_size;
public int dbcc_devicetype;
public int dbcc_reserved;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
public byte[] dbcc_classguid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] dbcc_name;
}
public void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE) //Device state has changed
{
switch (m.WParam.ToInt32())
{
case DBT_DEVICEARRIVAL: //New device arrives
DEV_BROADCAST_HDR hdr;
hdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_HDR));
if (hdr.dbch_devicetype == DBT_DEVTYP_VOLUME) //If it is a USB Mass Storage or Hard Drive
{
//Save Device name
DEV_BROADCAST_DEVICEINTERFACE deviceInterface;
string deviceName = "";
deviceInterface = (DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_DEVICEINTERFACE));
deviceName = new string(deviceInterface.dbcc_name).Trim();
}
}
}
}
但是deviceName
总是返回一个包含非感知字符的字符串。我在CharSet
结构中更改了DEV_BROADCAST_DEVICEINTERFACE
并将dbcc.name
声明为字符串,但结果是相同的。
我想避免从注册表中读取,在我读过的所有内容I have seen中,只有在DEV_BROADCAST_HEADER
时才可以将DEV_BROADCAST_DEVICEINTERFACE
投射到dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE
。在我的例子中,dbch_devicetype是2,而不是5,我正在使用一些常见的USB大容量存储设备。我究竟做错了什么?提前谢谢!
答案 0 :(得分:0)
也许,有一种更优雅的方式来解决这个问题,但至少,经过长时间的搜索,这似乎有效。
一方面,我注册了应用程序以便接收正确的信息以将其转换为DEV_BROADCAST_DEVICEINTERFACE
结构(在这种情况下DEV_BROADCAST_HEADER.dbch_devicetype
为5)。所以,我能够检索VID和PID信息。另一方面,我保留WndProc收到的第一个Windows消息,以检索Windows在连接USB设备时所分配的卷(DEV_BROADCAST_HEADER.dbch_devicetype
为2)。然后,我收到两条消息。
在代码中:
public const int WM_DEVICECHANGE = 0x219;
public const int DBT_DEVTYP_VOLUME = 0x00000002;
public const int DBT_DEVICEARRIVAL = 0x8000;
public const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;
private IntPtr notificationHandle;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags);
[StructLayout(LayoutKind.Sequential)]
internal class DEV_BROADCAST_HDR
{
public int dbch_size;
public int dbch_devicetype;
public int dbch_reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DEV_BROADCAST_DEVICEINTERFACE
{
public int dbcc_size;
public int dbcc_devicetype;
public int dbcc_reserved;
public Guid dbcc_classguid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] dbcc_name;
}
public void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE) //Device state has changed
{
switch (m.WParam.ToInt32())
{
case DBT_DEVICEARRIVAL: //New device arrives
DEV_BROADCAST_HDR hdr;
hdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_HDR));
if (hdr.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) //If it is a USB Mass Storage or Hard Drive
{
//Save Device name
DEV_BROADCAST_DEVICEINTERFACE deviceInterface = (DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_DEVICEINTERFACE));
deviceName = new string(deviceInterface.dbcc_name);
deviceNameFiltered = deviceName.Substring(0, deviceName.IndexOf('{'));
vid = GetVid(deviceName);
pid = GetPid(deviceName);
}
if (hdr.dbch_devicetype == DBT_DEVTYP_VOLUME)
{
DEV_BROADCAST_VOLUME volume;
volume = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
//Translate mask to device letter
driveLetter = DriveMaskToLetter(volume.dbcv_unitmask);
}
}
}
要注册应用程序以便接收正确的信息以将其强制转换为DEV_BROADCAST_DEVICEINTERFACE
结构,必须从Form类调用最后一个RegisterUsbDeviceNotification
方法,并将其窗口处理程序作为参数。
public void RegisterUsbDeviceNotification(IntPtr windowHandle)
{
DEV_BROADCAST_DEVICEINTERFACE deviceInterface = new DEV_BROADCAST_DEVICEINTERFACE
{
dbcc_classguid = GuidDevinterfaceUSBDevice,
dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
dbcc_reserved = 0,
};
deviceInterface.dbcc_size = Marshal.SizeOf(deviceInterface);
IntPtr buffer = Marshal.AllocHGlobal(deviceInterface.dbcc_size);
Marshal.StructureToPtr(deviceInterface, buffer, true);
notificationHandle = RegisterDeviceNotification(windowHandle, buffer, 0);
}