Link to home
Start Free TrialLog in
Avatar of Anjinsan5
Anjinsan5

asked on

Help with MSCOMM and enumerating COM ports...

I am working on an application in VB6 which communicates with an external device via a USB/serial adapter (via a virtual COM port) and uses the MSCOMM control for communication.  In the form_load event(see attached code), I use a For...Next statement to compile a list of all available COM ports in which I add to a combobox control for the user to select from.  The problem I am running into (mainly on laptops) is that the internal modem (usually COM3) is added to this list and when the user selects this port my program's error handling does not throw up an error message but rather attempts to communicate serially with the modem.    

1.  What I am trying to do is detect which port the modem is connected to (on Form_load) and remove that port from the list of available COM ports the user can select from.  
2.  Ive also noticed that if the modem port is set to say COM 2, my device (say COM4) is detected as a modem in my routine.  
 
Private Sub Form_Load()
Dim port, MyPorts
Dim totalport
Dim X As Single
Dim sInput As String
Dim ModemFind As Boolean
'Compile list of ports and add to combobox
For port = 1 To 16
            MSComm1.CommPort = port
            MSComm1.Settings = "9600,N,8,1"
            MSComm1.InputLen = 0
            On Error Resume Next
            MSComm1.PortOpen = True
            If Err.Number = 8002 Then
            Err.Clear
            End If
            If Err.Number = 8005 Then
            Err.Clear
            End If
If Err = 0 Then
        If MSComm1.PortOpen = True Then
            MSComm1.PortOpen = False
            cboCommPort.AddItem (CStr(port))
            totalport = totalport + 1
        End If
'Use this code to detect the modem port        
If MSComm1.PortOpen Then
            MSComm1.Output = "ATV1Q0" & Chr$(13)
            X = Timer
            While Timer - X < 1
                DoEvents
            Wend
            sInput = sInput & MSComm1.Input
            'MSComm1.PortOpen = False
            If InStr(sInput, "OK" & vbCrLf) <> 0 Then
            cboCommPort.RemoveItem (CStr(port))
            MsgBox "       Modem detected on COM" & port
            ModemFind = True
            MSComm1.PortOpen = False
            Exit For
            End If
            If ModemFind = False Then
            Resume Next
            End If
            If cboCommPort.Text = "" Then cboCommPort.Text = CStr(port)
         End If
    End If
Next
FrmMain.StatusBar1.Panels(1).Text = "Detected available PC Comm. Ports..."
start_tmrStatusBarText
Err.Clear

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of melmers
melmers
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Anjinsan5
Anjinsan5

ASKER

Thanks for the suggestion.  I have tried that however what happens is if my modem is set to (say COM8) and my device is on (say COM 4) it will add both COM ports to the combobox as options for the user.  Now, if my modem is set to (say COM2) and my device is any port higher, it will exit the for loop (as shown in my code), add the modem port to the combobox, and not scan for any further ports.

What I am trying to achieve, is for Form_load to scan for all available COM ports and add them to a combobox control, however if it detects the internal modem (lines 27-40) it will not add that port to the combobox.  It seems I need some alteration to code to allow the loop to continue to scan after it has detected the modem port and disregarded it to find any additional COM ports.  So, for example,  if COM1, COM2, COM3 (internal modem), and COM8(my device) are found then all ports are added to the combobox except COM3 (internal modem).  Thanks.
 
Remove teh Exit For Statement from line 40 so it loop through all COM-Ports
It now loops through all COM ports, however it still adds the modem port to the combobox as a selectable option for the user.  My goal is to make sure the user doesn't have the option of selecting the modem port as an usable COM port (therefore when my code detects the modem it removes it from the combobox, or never adds it to the combobox in the first place).  It would be even better if the Combobox.text property would display the COM port which my device is connected to as the default option.  Any ideas?
Are there any Response from your device when you send the AT command?
Have you reset the sInput variable at the end of the
Write at Line 41 after the End If
sInput = ""
Ok I have it somewhat working with the following code below.  The modem port is no longer being added to the combobox, however I had it working properly when the device was connected to COM4, but for some reason it does not communicate with the device when the device was connected to COM6.  Strange, any ideas?
'----------------------------------------------------------------------------------
'Detect Modem Port First
For port = 1 To 16
            sInput = ""
            MSComm1.CommPort = port
            MSComm1.Settings = "9600,N,8,1"
            MSComm1.InputLen = 0
            On Error Resume Next
            MSComm1.PortOpen = True
            If Err.Number = 8002 Then
            Err.Clear
            End If
            If Err.Number = 8005 Then
            Err.Clear
            End If
If Err = 0 Then
        If MSComm1.PortOpen = True Then
            MSComm1.Output = "ATV1Q0" & Chr$(13)
            X = Timer
            While Timer - X < 1
                DoEvents
            Wend
            sInput = sInput & MSComm1.Input
            If InStr(sInput, "OK" & vbCrLf) <> 0 Then
                    MsgBox "       Modem detected on COM" & port
            MSComm1.PortOpen = False
            ElseIf InStr(sInput, "OK" & vbCrLf) = 0 Then
            cboCommPort.AddItem (CStr(port))
            totalport = totalport + 1
            MSComm1.PortOpen = False
            End If
            If cboCommPort.Text = "" Then cboCommPort.Text = CStr(port)
        End If
    End If
FrmMain.StatusBar1.Panels(1).Text = "Detected available PC Comm. Ports..."
start_tmrStatusBarText
Err.Clear
Next
'-------------------------------------------------------------------------------------

Open in new window

The modem port issue seems resolved and the device will communicate with ports (1-4) however when tested on COM6 and up (COM5 was busy) it will not communicate nor react to my error handling.  
Hi!

Why don't you use EnumPorts from the windows API?
I think it will be the best way to do it...

See: http://www.ex-designz.net/apidetail.asp?api_id=556

Thanks for the article.  I have looked into the Windows API solution however I don't believe it will resolve the issue I'm having now.  I am able to list the available COM ports and now weed out the modem port, however my issue is figuring out why there is no communication between the device and mscomm after COM4.
It's possible that other devices are using those ports, like bluetooth devices, or modems. You should use the default port COM1.
I have it fully working now, I just had to make a few changes to other parts of my code.  One final question, is there any way to have the combobox.text property default to the COM port which my device is connected to?
Do you know what is this port, or you have a way do know it?
That is my issue; it can be different every time the user plugs the device in depending on what COM port is assigned to the USB/serial converter.  I think I will throw a serial command at the port and if the device responds then I will confirm it is my device.  Thanks for your help!
Wasn't it my answer...?

...snifffff
User generated imageThe registry contains infos on the COM ports.
The registry COM port informations are always up to date !
-Here is a sample :
'Read COM ports from registry :

Private Sub Command1_Click()

Const REG_SZ = 1
Const REG_DWORD = 4
Const REG_BINARY = 3
Const REG_MULTI_SZ = 7
Const REG_EXPAND_SZ = 2
Const HKCU = &H80000001
Const HKLM = &H80000002

Set Registry = GetObject("winmgmts:\\.\root\default:StdRegProv")

'myKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
myKey = "HARDWARE\DEVICEMAP\SERIALCOMM"
Registry.EnumValues HKLM, myKey, valueNames, valueTypes

If Not IsNull(valueNames) Then
    For i = 0 To UBound(valueNames)
        myVal = valueNames(i)
        
        If valueTypes(i) = REG_SZ Then
            Registry.GetStringValue HKLM, myKey, myVal, DataCOM12
            AutoRedraw = True
            Print " " & myVal & ": " & DataCOM12
        End If
    Next
End If
                                          
End Sub

Open in new window