BBC BASIC for Windows
Programming >> Communication and Input/Output >> Identifying non-existent COM ports?
http://bb4w.conforums.com/index.cgi?board=communication&action=display&num=1412347824

Identifying non-existent COM ports?
Post by g3nrw on Oct 3rd, 2014, 2:50pm

I have a program that needs to make a list of non-existent COM ports, in the range COM1..COM20.

This is a starting point:

Code:
FOR n% = 1 TO 20
   handle% = OPENUP (... "COM"+STR$(n%) ......)
   
   IF handle% <> 0 THEN
       : Port exists *and* is free for use
       CLOSE handle%
   ELSE
       : Port exists but is in use, *or* port does not exist
   ENDIF

NEXT
 

Is there a simple way to distinguish in the ELSE case whether the port is already in use or it does not exist, without digging into the registry?

--
Ian

Re: Identifying non-existent COM ports?
Post by rtr2 on Oct 3rd, 2014, 3:52pm

on Oct 3rd, 2014, 2:50pm, g3nrw wrote:
Is there a simple way to distinguish whether the port is already in use or it does not exist

I don't know. Have you checked whether GetLastError returns something different?

Richard.

Re: Identifying non-existent COM ports?
Post by g3nrw on Oct 3rd, 2014, 9:12pm

on Oct 3rd, 2014, 3:52pm, g4bau wrote:
Have you checked whether GetLastError returns something different?


No I haven't, but I have decided that my simple program was a crude way of getting the answer.

Instead, I have been looking in the registry. The key values I really want to read are at \HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM.

However, on trying your examples at http://www.cix.co.uk/~rrussell/bbcwin/manual/bbcwine.html#registry I have discovered that these code snippets only work if the key path is below HKEY_CURRENT_USER.

I have spent a therapeutic couple of hours or so browsing the Microsoft sites for details of "RegOpenKeyEx" etc, to try to relate it to your BB4W command:
~~~~~~~~~~~~~~~~
SYS "RegOpenKeyEx", &80000001, Key$, 0, &20001, ^K% TO R%
~~~~~~~~~~~~~~~~

I assume "&20001" is the security access code that allows you to read the key values, but what is the "&80000001" parameter? Is this a code that specifies that the key root is HKEY_CURRENT_USER, I wonder?

Looking at this site ...

http://msdn.microsoft.com/en-us/library/aa392722%28v=vs.85%29.aspx

... I divined that HKEY_LOCAL_MACHINE = &H80000002, so I tried this constant instead of &H80000001, but I couldn't get this to work:

Code:
      DIM TempBuffer% 255

      Key$ = "HARDWARE\DEVICEMAP\SERIALCOMM"

      SYS "RegOpenKeyEx", &80000002, Key$, 0, &20001, ^K% TO R%
      IF R% = 0 THEN
        L% = 255 : SYS "RegQueryValueEx", K%, "String", 0, ^T%, TempBuffer%, ^L% TO R%
        IF R% = 0 TempBuffer%?(L%-1) = 13 : String$ = $TempBuffer%
        L% = 4 : SYS "RegQueryValueEx", K%, "Integer", 0, ^T%, ^V%, ^L% TO R%
        IF R% = 0 Integer% = V%
        SYS "RegCloseKey", K%
      ENDIF

      PRINT "String$=" + String$
 


I'm sure I've missed something obvious here!

Question, then, is do you know how I can change the key root to HKEY_LOCAL_MACHINE?

--
Ian

Re: Identifying non-existent COM ports?
Post by rtr2 on Oct 3rd, 2014, 10:13pm

on Oct 3rd, 2014, 9:12pm, g3nrw wrote:
No I haven't, but I have decided that my simple program was a crude way of getting the answer.

Well, calling GetLastError (if it works) is at least legal, whereas direct registry access to system locations isn't (there is no guarantee that key/value names will remain the same in different versions of Windows).

The officially supported way of enumerating the serial ports is to use WMI, and is documented in the BB4W Wiki:

http://bb4w.wikispaces.com/Enumerating+serial+ports

I can't believe you didn't find that. tongue

Richard.
Re: Identifying non-existent COM ports?
Post by g3nrw on Oct 4th, 2014, 12:55pm

Using GetLastError:

Code:
      FOR p% = 1 TO 255
        port% = OPENIN("COM" + STR$(p%)  + ": 115200,N,8,1")
        SYS "GetLastError" TO winerr%
  
        CASE winerr% OF
          WHEN 0:
            PRINT "COM" + STR$(p%) + "  Free"
            CLOSE# port%
      
          WHEN 1:
            PRINT "COM" + STR$(p%) + "  In Use"
      
        ENDCASE
  
      NEXT
 

This works OK, but only for port name values "COMn" (this includes VSPE ports).

If com0com is in use, you have no idea how the port name values are defined -- the user can specify any value -- so the above code won't work.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Re WMI, http://bb4w.wikispaces.com/Enumerating+serial+ports , I tried that. Strangely, it only enumerates the com0com ports (but doesn't do this properly), and ignores COM ports altogether! (This is under Windows 7/32).


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So the only accurate source of port name values that I can find is in the registry. Problem now is discovering the names, so I can then retrieve the values.

--
Ian


Re: Identifying non-existent COM ports?
Post by rtr2 on Oct 4th, 2014, 2:06pm

on Oct 4th, 2014, 12:55pm, g3nrw wrote:
Strangely, it only enumerates the com0com ports (but doesn't do this properly), and ignores COM ports altogether! (This is under Windows 7/32).

To reiterate, that is the official method for enumerating serial ports in Windows. If it is not returning the port(s) in which you are interested your system is broken and you cannot expect anything to work correctly.

Quote:
So the only accurate source of port name values that I can find is in the registry.

It isn't legitimate to read the registry directly - it is a hack which is not guaranteed to work on different versions of Windows. You should fix the cause of the WMI problem, not attempt to work around it.

My guess would be that COM0COM is broken; I would suggest that you try using Virtual Null Modem instead. That's the utility I use and I have not noticed it causing any unexpected behaviour:

http://www.virtual-null-modem.com/

Richard.