none
VS2010上用VB.NET写USB接口程序,枚举设备接口出问题,呼叫高手指点……程序有点长,得多费神了。 RRS feed

  • 问题

  • Option Strict Off
    Option Explicit On
    Public Class Form1
        'Private Structure GUID
        'Dim Data1 As Integer
        ' Dim Data2 As Short
        ' Dim Data3 As Short
        '<VBFixedArray(7)> Dim Data4() As Byte

        'Public Sub Initialize()
        '    ReDim Data4(7)
        'End Sub
        'End Structure


        Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
        Public Const GENERIC_READ = &H80000000
        Public Const GENERIC_WRITE = &H40000000
        Public Const FILE_SHARE_READ = &H1
        Public Const FILE_SHARE_WRITE = &H2
        Private Const DIGCF_DEFAULT As Integer = &H1
        Private Const DIGCF_PRESENT As Integer = &H2
        Private Const DIGCF_DEVICEINTERFACE As Integer = &H10
        Private Const DIGCF_ALLCLASSES As Integer = &H4
        Private Const DIGCF_PROFILE As Integer = &H8

        Private Const DICS_ENABLE As Integer = &H1
        Private Const DICS_DISABLE As Integer = &H2
        Private Const DICS_FLAG_GLOBAL As Integer = &H1
        Private Const DICS_FLAG_CONFIGSPECIFIC As Integer = &H2
        Private GUID_DEVCLASS_PORTS As Guid
        Private Const INVALID_HANDLE_VALUE As Integer = -1
        Private Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
        Private Const SPDRP_DEVICEDESC As Integer = &H0
        Private Const SPDRP_CLASS As Integer = &H7
        Private Const SPDRP_CLASSGUID As Integer = &H8
        Private Const SPDRP_DRIVER As Integer = &H9
        Private Const SPDRP_FRIENDLYNAME As Integer = &HC
        Private Const SPDRP_ENUMERATOR_NAME As Integer = &H16
        Private Const DIF_PROPERTYCHANGE As Integer = &H12S
        Private Const OPEN_EXISTING = 3
        Const FILE_ATTRIBUTE_NORMAL = &H80

        Const MyVendorID = &H925
        Const MyProductID = &H1234

        Dim Result As Long
        Dim Needed As Long
        Dim DetailData As Long
        Dim DetailDataBuffer() As Byte  
        Dim DevicePathName As String
        Dim HidDevice As Long

        Dim LastDevice As Boolean = False
        Dim MyDeviceDetected As Boolean = False

        Dim MyDeviceInterfaceData As SP_DEVICE_INTERFACE_DATA
        Dim MyDeviceInfoData As SP_DEVINFO_DATA
        Dim MyDeviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA
        Dim DeviceAttributes As HIDD_ATTRIBUTES
        Dim vbUnicode As VbStrConv


        Private Declare Function SetupDiGetClassDevs Lib "setupapi" Alias "SetupDiGetClassDevsA" (ByVal ClassGuid As Guid, ByVal Enumerator As Integer, ByVal hWndParent As Integer, ByVal Flags As Integer) As Integer
        Private Declare Function SetupDiDestroyDeviceInfoList Lib "setupapi" (ByVal DeviceInfoSet As Integer) As Integer
        Private Declare Function SetupDiEnumDeviceInfo Lib "setupapi" (ByVal DeviceInfoSet As Integer, ByVal MemberIndex As Integer, ByRef DeviceInfoData As SP_DEVINFO_DATA) As Integer
        Private Declare Function SetupDiGetDeviceRegistryProperty Lib "setupapi" Alias "SetupDiGetDeviceRegistryPropertyA" (ByVal DeviceInfoSet As Integer, ByRef DeviceInfoData As SP_DEVINFO_DATA, ByVal Property_Renamed As Integer, ByRef PropertyRegDataType As Integer, ByVal PropertyBuffer As Integer, ByVal PropertyBufferSize As Integer, ByRef RequiredSize As Integer) As Integer
        Private Declare Function SetupDiSetClassInstallParams Lib "setupapi" Alias "SetupDiSetClassInstallParamsA" (ByVal DeviceInfoSet As Integer, ByRef DeviceInfoData As SP_DEVINFO_DATA, ByRef ClassInstallParams As SP_CLASSINSTALL_HEADER, ByVal ClassInstallParamsSize As Integer) As Integer
        Private Declare Function SetupDiCallClassInstaller Lib "setupapi" (ByVal InstallFunction As Integer, ByVal DeviceInfoSet As Integer, ByRef DeviceInfoData As SP_DEVINFO_DATA) As Integer
        Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Integer
        Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
        Public Event EnumDevicesProc(ByVal lIndex As Integer, ByVal sDeviceName As String, ByVal sDeviceClassName As String, ByVal sDeviceFriendlyName As String, ByVal sDeviceEnumeratorName As String, ByVal sDeviceClassGuid As String)


        Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
        Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByRef lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
        Public Declare Function HidD_FreePreparsedData Lib "hid.dll" (ByRef PreparsedData As Long) As Long
        Public Declare Function HidD_GetAttributes Lib "hid.dll" (ByVal HidDeviceObject As Long, ByRef Attributes As HIDD_ATTRIBUTES) As Long

        Public Declare Function HidD_GetHidGuid Lib "hid.dll" (ByRef HidGuid As Guid) As Long
        Public Declare Function HidD_GetPreparsedData Lib "hid.dll" (ByVal HidDeviceObject As Long, ByRef PreparsedData As Long) As Long
        'Public Declare Function HidP_GetCaps Lib "hid.dll" (ByVal PreparsedData As Long, ByRef Capabilities As HIDP_CAPS) As Long
        Public Declare Function HidP_GetValueCaps Lib "hid.dll" (ByVal ReportType As Integer, ByRef ValueCaps As Byte, ByRef ValueCapsLength As Integer, ByVal PreparsedData As Long) As Long
        Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal dest As String, ByVal source As Long) As String
        Public Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal source As Long) As Long
        Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByRef lpBuffer As Byte, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
        Public Declare Function RtlMoveMemory Lib "kernel32" (ByVal dest As Byte, ByVal src As SP_DEVICE_INTERFACE_DETAIL_DATA, ByVal Count As Long) As Long
        Public Declare Function SetupDiCreateDeviceInfoList Lib "setupapi.dll" (ByRef ClassGuid As Guid, ByVal hwndParent As Long) As Long
        Public Declare Function SetupDiDestroyDeviceInfoList Lib "setupapi.dll" (ByVal DeviceInfoSet As Long) As Long
        Public Declare Function SetupDiEnumDeviceInterfaces Lib "setupapi.dll" (ByVal DeviceInfoSet As Long, ByVal DeviceInfoData As Long, ByRef InterfaceClassGuid As Guid, ByVal MemberIndex As Long, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) As Long
        Public Declare Function SetupDiGetClassDevs Lib "setupapi.dll" Alias "SetupDiGetClassDevsA" (ByRef ClassGuid As Guid, ByVal Enumerator As String, ByVal hwndParent As Long, ByVal Flags As Long) As Long
        Public Declare Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" Alias "SetupDiGetDeviceInterfaceDetailA" (ByVal DeviceInfoSet As Long, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByVal DeviceInterfaceDetailData As Long, ByVal DeviceInterfaceDetailDataSize As Long, ByRef RequiredSize As Long, ByVal DeviceInfoData As Long) As Long
        Public Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByRef lpBuffer As Byte, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long


        Public Structure SP_DEVICE_INTERFACE_DATA
            Dim cbSize As Long
            Dim InterfaceClassGuid As System.Guid
            Dim Flags As Long
            Dim Reserved As Long
        End Structure

        Public Structure SP_DEVINFO_DATA
            Dim cbSize As Integer
            Dim ClassGuid As System.Guid
            Dim DevInst As Integer
            Dim Reserved As Integer
        End Structure

        Public Structure SP_DEVICE_INTERFACE_DETAIL_DATA
            Dim cbSize As Long
            Dim DevicePath As Byte
        End Structure

        Public Structure SP_CLASSINSTALL_HEADER
            Dim cbSize As Integer
            Dim InstallFunction As Integer
        End Structure

        Public Structure SP_PROPCHANGE_PARAMS
            Dim ClassInstallHeader As SP_CLASSINSTALL_HEADER
            Dim StateChange As Integer
            Dim Scope As Integer
            Dim HwProfile As Integer
        End Structure

        Public Structure HIDD_ATTRIBUTES
            Dim Size As Long
            Dim VendorID As Integer
            Dim ProductID As Integer
            Dim VersionNumber As Integer
        End Structure

        Sub fillArray(ByVal t() As Integer)
            Dim x As Integer

            For x = 0 To 63
                t(x) = x + 10
            Next x
        End Sub

        Sub Main()
            Dim T(63) As Integer           'Define a large array of data
            Dim S(63) As Integer
            fillArray(T)
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim HidGuid As Guid
            Dim DeviceInfoSet As Long
            Dim vbNullString As String = Nothing
            Dim MemberIndex As Long

            Result = HidD_GetHidGuid(HidGuid) '取得HID群组的GUID
            DeviceInfoSet = SetupDiGetClassDevs(HidGuid, vbNullString, 0, (DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE)) '取得所有HID信息的结构数组      才到这里就提示错误“对 PInvoke 函数“VBtoUSB2!VBtoUSB2.Form1::SetupDiGetClassDevs”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。”

     


            MemberIndex = 0

            Do
                MyDeviceInterfaceData.cbSize = Len(MyDeviceInterfaceData)
                Result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, HidGuid, MemberIndex, MyDeviceInterfaceData) '识别每一个HID接口
                If Result = 0 Then LastDevice = True
                If Result <> 0 Then
                    MyDeviceInfoData.cbSize = Len(MyDeviceInfoData)
                    Result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, MyDeviceInterfaceData, 0, 0, Needed, 0) '取得设备路径(为了分配空间)

                    DetailData = Needed
                    MyDeviceInterfaceDetailData.cbSize = Len(MyDeviceInterfaceDetailData)
                    ReDim DetailDataBuffer(Needed)
                    Call RtlMoveMemory(DetailDataBuffer(0), MyDeviceInterfaceDetailData, 4)
                    Result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, MyDeviceInterfaceData, DetailDataBuffer(0), DetailData, Needed, 0)  '取得设备路径
                    DevicePathName = CStr(DetailDataBuffer(0))
                    DevicePathName = StrConv(DevicePathName, vbUnicode)
                    'DevicePathName = padRight(DevicePathName, Len(DevicePathName) - 4)


                    HidDevice = CreateFile(DevicePathName, GENERIC_READ Or GENERIC_WRITE, (FILE_SHARE_READ Or FILE_SHARE_WRITE), 0, OPEN_EXISTING, 0, 0) '取得设备的标示代号
                    DeviceAttributes.Size = Len(DeviceAttributes)
                    Result = HidD_GetAttributes(HidDevice, DeviceAttributes) '取得厂商与产品ID
                    If (DeviceAttributes.VendorID = MyVendorID) And (DeviceAttributes.ProductID = MyProductID) Then
                        MyDeviceDetected = True
                    Else
                        MyDeviceDetected = False
                        Result = CloseHandle(HidDevice)
                    End If
                End If
                MemberIndex = MemberIndex + 1
            Loop Until (LastDevice = True) Or (MyDeviceDetected = True)

     


        End Sub

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Call Main()
        End Sub
    End Class

     

    2011年10月9日 7:12

答案

全部回复

  • 又遇到新问题了。

     

    在VB6.0 的时候获取的设备地址GUID的声明如下:

    Public Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(7) As Byte
    End Type

    但转到VB2010上的时候,GUID似乎系统已经有声明了,但感觉获取的格式不对,故进行了如下声明:

        Private Structure GUID
            Dim Data1 As Integer
            Dim Data2 As Short
            Dim Data3 As Short
            <VBFixedArray(7)> Dim Data4() As Byte
            Public Sub Initialize()
                ReDim Data4(7)
            End Sub
        End Structure

    Dim HidGuid as GUID

    但似乎声明出来的GUID,在调用API库的时候,不认,提示错误为:

    Private Declare Function SetupDiGetClassDevs Lib "setupapi" Alias "SetupDiGetClassDevsA" (ByRef ClassGuid As GUID, ByVal Enumerator As Integer, ByVal hwndParent As Integer, ByVal Flags As Integer) As Integer

    Result = HidD_GetHidGuid(HidGuid)    变量“HidGuid”在赋值前按引用传递。可能会在运行时导致null引用异常,请确保结构或者所引用成员在使用前已经初始化。

     

    求有解决方案的朋友指点一二,不胜感激!

    2011年10月10日 1:45
  • 2011年10月10日 4:05
    版主
  •  

    也试过去了,就直接

    Dim HidGuid As System.Guid调用,在枚举设备接口的时候总时返回0

    以下是调试的变量值:
    HidGuid:{4d1e55b2-f16f-11cf-88cb-001111000030}
    MyDeviceInterfaceData.cbSize:24
    something:1784

    调用这个API函数的时候:SetupDiEnumDeviceInterfaces返回的Resutl总是为0,
    MyDeviceInterfaceData下的:cbSize为24 Flags为0 InterfaceClassGuid为{00000000-0000-0000-0000-000000000000}
    得到的错误是1784,貌似说:所提供的用户缓冲区对所申请的操作无效。

    烦请再帮我看一下好吗,麻烦了,谢谢

    2011年10月10日 5:42
  • <DllImport("setupapi.dll", _
        EntryPoint:="SetupDiGetClassDevsW", _
        SetLastError:=True, _
        CharSet:=CharSet.Unicode, _
        ExactSpelling:=True, _
        PreserveSig:=True, _
        CallingConvention:=CallingConvention.Winapi)> _
        Private Shared Function SetupDiGetClassDevs( _
        ByRef ClassGuid As GUID, _
        ByVal Enumerator As Integer, _
        ByVal hwndParent As Integer, _
        ByVal Flags As Integer) As Integer
        End Function


    http://feiyun0112.cnblogs.com/
    2011年10月10日 5:57
    版主
  • 调用DeviceInfoSet = SetupDiGetClassDevs(HidGuid, vbNullString, 0, (DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE))

    返回值:DeviceInfoSet =2280336

    HidGuid={4d1e55b2-f16f-11cf-88cb-001111000030}

    再调用 Result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, HidGuid, MemberIndex, MyDeviceInterfaceData)

    返回Result =0

    something = GetLastError()的错误代码:1784(提供给请求操作的用户缓冲区无效),这个似乎是识别不了哦。

    2011年10月10日 6:23
  • <DllImport("setupapi.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
      Public Shared Function SetupDiEnumDeviceInterfaces(ByVal hDevInfo As IntPtr, _
        ByRef devInfo As SP_DEVICE_INTERFACE_DATA, ByRef interfaceClassGuid As Guid, _
        ByVal memberIndex As UInt32, ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA) As Boolean
      End Function

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure SP_DEVICE_INTERFACE_DATA
        Public cbSize As UInteger
        Public InterfaceClassGuid As Guid
        Public Flags As UInteger
        Public Reserved As IntPtr
    End Structure


    http://feiyun0112.cnblogs.com/
    2011年10月10日 6:31
    版主
  • 谢谢了,改着改着就行了。
    2011年10月11日 6:39