Results 1 to 8 of 8

Thread: [RESOLVED] Need help with API Communication Port State reading

  1. #1

    Thread Starter
    Addicted Member beic's Avatar
    Join Date
    Jun 2012
    Posts
    150

    Resolved [RESOLVED] Need help with API Communication Port State reading

    Hi there,

    Is there a way to check the State/Status of the port, port presence, removed device from com port while the application is running with mentioned functions below?

    I'm using these API functions:

    Code:
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function GetLastError Lib "kernel32" () As Long
    Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Long) As Long
    Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Long) As Long
    Private Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
    Private Declare Function BuildCommDCB Lib "kernel32" Alias "BuildCommDCBA" (ByVal lpDef As String, lpDCB As DCB) As Long
    Private Declare Function SetCommState Lib "kernel32" (ByVal hFile As Long, lpDCB As DCB) As Long
    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
    Any help would be appreciated,

    Kind regards,
    Viktor
    Last edited by beic; Feb 24th, 2020 at 04:32 PM. Reason: typo

  2. #2
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,068

    Re: Need help with API Communication Port State reading

    You can enum the current devices using wmi and compare the list with a previous copy to detect removals

    Class supports state information as well:
    https://docs.microsoft.com/en-us/win...n32-serialport

    There is probably a notification message you can register to receive from windows somehow too. drive notification change
    or something. I know DefineDosDevice can generate this message if you want to hunt down the details.

    Code:
    Private Sub LoadPorts()
        Dim strComputer As String
        Dim objWMIService As Object
        Dim colItems As Object
        Dim objItem As Object
        
        On Error Resume Next
        
        strComputer = "."
        Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
        Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_SerialPort", , 48)
        
        For Each objItem In colItems
            CboPort.AddItem objItem.DeviceID & " " & objItem.Description
        Next
           
        Set objItem = Nothing
        Set colItems = Nothing
        Set objWMIService = Nothing
        
        CboPort.ListIndex = 0
        
    End Sub
    Last edited by dz32; Feb 24th, 2020 at 09:37 PM.

  3. #3
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,156

    Re: Need help with API Communication Port State reading

    Here is a fast EnumSerialPorts implementation:

    thinBasic Code:
    1. Option Explicit
    2.  
    3. Private Declare Function QueryDosDevice Lib "kernel32" Alias "QueryDosDeviceA" (ByVal lpDeviceName As Long, ByVal lpTargetPath As String, ByVal ucchMax As Long) As Long
    4.  
    5. Public Function EnumSerialPorts() As Variant
    6.     Dim sBuffer         As String
    7.     Dim lIdx            As Long
    8.     Dim vRetVal         As Variant
    9.     Dim lCount          As Long
    10.    
    11.     ReDim vRetVal(0 To 255) As Variant
    12.     sBuffer = String$(100000, 1)
    13.     Call QueryDosDevice(0, sBuffer, Len(sBuffer))
    14.     sBuffer = vbNullChar & sBuffer
    15.     For lIdx = 1 To 255
    16.         If InStr(1, sBuffer, vbNullChar & "COM" & lIdx & vbNullChar, vbTextCompare) > 0 Then
    17.             vRetVal(lCount) = "COM" & lIdx
    18.             lCount = lCount + 1
    19.         End If
    20.     Next
    21.     If lCount = 0 Then
    22.         vRetVal = Array()
    23.     Else
    24.         ReDim Preserve vRetVal(0 To lCount - 1) As Variant
    25.     End If
    26.     EnumSerialPorts = vRetVal
    27. End Function
    28.  
    29. Private Sub Form_Load()
    30.     Dim vElem           As Variant
    31.    
    32.     For Each vElem In EnumSerialPorts
    33.         Debug.Print vElem
    34.     Next
    35. End Sub
    For new USB serial ports arrival you can use RegisterDeviceNotification to get WM_DEVICECHANGE message like this:

    thinBasic Code:
    1. Option Explicit
    2.  
    3. '--- Windows Messages
    4. Private Const WM_DEVICECHANGE               As Long = &H219
    5. '--- for RegisterDeviceNotification
    6. Private Const DEVICE_NOTIFY_WINDOW_HANDLE   As Long = &H0
    7. Private Const DBT_DEVTYP_DEVICEINTERFACE    As Long = &H5
    8. Private Const DBT_DEVICEARRIVAL             As Long = &H8000&
    9. Private Const DBT_DEVICEREMOVECOMPLETE      As Long = &H8004&
    10. Private Const GUID_DEVINTERFACE_USB_DEVICE  As String = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
    11.  
    12. Private Declare Function RegisterDeviceNotification Lib "user32" Alias "RegisterDeviceNotificationA" (ByVal hRecipient As Long, ByRef NotificationFilter As Any, ByVal Flags As Long) As Long
    13. Private Declare Function UnregisterDeviceNotification Lib "user32" (ByVal Handle As Long) As Long
    14. Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpsz As Long, pclsid As Any) As Long
    15.  
    16. Private Type DEV_BROADCAST_DEVICEINTERFACE
    17.     dbcc_size           As Long
    18.     dbcc_devicetype     As Long
    19.     dbcc_reserved       As Long
    20.     dbcc_classguid(0 To 3) As Long
    21.     dbcc_name           As Long
    22. End Type
    23.  
    24. Private m_hDevNotify                As Long
    25. Private m_pSubclass                 As IUnknown
    26.  
    27. Private Property Get pvAddressOfSubclassProc() As Form1
    28.     Set pvAddressOfSubclassProc = InitAddressOfMethod(Me, 5)
    29. End Property
    30.  
    31. Private Sub Form_Load()
    32.     Dim uFilter         As DEV_BROADCAST_DEVICEINTERFACE
    33.  
    34.     '--- on device insert/eject notify w/ WM_DEVICECHANGE
    35.     uFilter.dbcc_size = Len(uFilter)
    36.     uFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE
    37.     Call CLSIDFromString(StrPtr(GUID_DEVINTERFACE_USB_DEVICE), uFilter.dbcc_classguid(0))
    38.     m_hDevNotify = RegisterDeviceNotification(hWnd, uFilter, DEVICE_NOTIFY_WINDOW_HANDLE)
    39.     Set m_pSubclass = InitSubclassingThunk(hWnd, Me, pvAddressOfSubclassProc.SubclassProc(0, 0, 0, 0, 0))
    40. End Sub
    41.  
    42. Private Sub Form_Unload(Cancel As Integer)
    43.     If m_hDevNotify <> 0 Then
    44.         Call UnregisterDeviceNotification(m_hDevNotify)
    45.         m_hDevNotify = 0
    46.     End If
    47. End Sub
    48.  
    49. Public Function SubclassProc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long, Handled As Boolean) As Long
    50.     Select Case wMsg
    51.     Case WM_DEVICECHANGE
    52.         Select Case wParam
    53.         Case DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE
    54.             Debug.Print "wParam=&H" & Hex(wParam), Timer
    55.         End Select
    56.         Handled = True
    57.     End Select
    58. End Function
    This uses the Modern Subclassing Thunk for the IDE-safe subclassing.

    For serial ports overlapped I/O you can check out this cSerialPortConnector class test project.

    cheers,
    </wqw>

  4. #4

    Thread Starter
    Addicted Member beic's Avatar
    Join Date
    Jun 2012
    Posts
    150

    Re: Need help with API Communication Port State reading

    Thank you all for the propositions and examples,

    I went with WMI implementation, because RegisterDeviceNotification on USB are detecting 4-6 times in a row after insertion because it's a virtual USB COM port device or the device driver is poorly written.

    Thank you again for your time!

  5. #5
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,156

    Re: Need help with API Communication Port State reading

    Quote Originally Posted by beic View Post
    Thank you all for the propositions and examples,

    I went with WMI implementation
    Which WMI implementation?

    Note that WMI is a feature for admin scripts that might be uninstalled on client machines for security reasons.

    cheers,
    </wqw>

  6. #6

    Thread Starter
    Addicted Member beic's Avatar
    Join Date
    Jun 2012
    Posts
    150

    Re: Need help with API Communication Port State reading

    Quote Originally Posted by wqweto View Post
    Which WMI implementation?
    Note that WMI is a feature for admin scripts that might be uninstalled on client machines for security reasons.
    Similar like mentioned in the second post above, I tried QueryDosDevice but it's slow as hell!

    Kind regards,
    Viktor

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,156

    Re: [RESOLVED] Need help with API Communication Port State reading

    How many serial ports are you enumerating? I have 10 ports and it’s instant here. It returns a simple cached string so I cannot see where the overhead would come from.

  8. #8

    Thread Starter
    Addicted Member beic's Avatar
    Join Date
    Jun 2012
    Posts
    150

    Re: [RESOLVED] Need help with API Communication Port State reading

    Quote Originally Posted by wqweto View Post
    How many serial ports are you enumerating? I have 10 ports and it’s instant here. It returns a simple cached string so I cannot see where the overhead would come from.
    I have only one USB to SERIAL adapter, so, only 1 port!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width