Home > Enterprise >  (VB.NET) Need to Change Ports on COM18 and COM19 to COM3 and COM4 in WinForm
(VB.NET) Need to Change Ports on COM18 and COM19 to COM3 and COM4 in WinForm

Time:06-17

I get new Win7 Offline PCs imaged with the wrong Com/Serial ports that I have to set up. Out of the box they are always COM18 and COM19 but they need to be COM3 and COM4. I am honestly so tired of manually changing them that I just want this built into a VB.NET 2.0 EXE WinForm that I run that sets other things up as well. Other message boards tell me Win7 is not supported so they can't help, but I have no control over the OS. Hoping StackOverflow will help.

I think I need to change the DeviceID, Caption, and Name in the Win32_SerialPort(?) but the only thing I can find is a SELECT query not an UPDATE or anything.

Here is what I am working with but changing to an UPDATE doesn't work.


Dim ConnOptions As New ConnectionOptions() With {.EnablePrivileges = True, .Timeout = EnumerationOptions.InfiniteTimeout}
Dim mOptions As New EnumerationOptions() With {.Rewindable = False, .ReturnImmediately = True, .DirectRead = True, .EnumerateDeep = False}
Dim mQuery1 As New SelectQuery("SELECT * FROM Win32_SerialPort WHERE Name LIKE '%COM18%'")

'Sample query I thought might work: UPDATE Win32_SerialPort SET DeviceID = "COM3" WHERE Name LIKE '%COM18%'")

Dim mScope As New ManagementScope($"\\{Environment.MachineName}\root\CIMV2", ConnOptions)
mScope.Connect()
Using moSearcher1 As New ManagementObjectSearcher(mScope, mQuery1, mOptions)
    If moSearcher1.Get().Equals("COM18") = True Then
        'DO SOMETHING HERE LIKE A POPUP
    End If
End Using

Am I stuck doing this manually every time or is there something I am missing (either in my code or I am way off base) to help automate this?

CodePudding user response:

The solution I was able to come up with was actually to get an older version of ProcMon (process monitor) and see exactly what was changing in the registry. From there I had to manually write registry edits. Still doesn't feel like the most efficient method, but it worked.

If anyone has this specific question as well, here are the registry edits that I did:

'***** ADD PORT NUMBER ENTRIES
C:\Windows\win.ini
'***** EDIT \Device\SiLabUser to "COM3" or "COM4"
HKLM\HARDWARE\DEVICEMAP\SERIALCOMM\
'***** EDIT sub keys PORTNAME and FRIENDLYNAME
HKLM\System\CurrentControlSet\Enum\USB\VID_10C8&PID_EP69&MI_00\8&6FD00A90&0&0000

CodePudding user response:

This post isn't a complete answer, but shows how one can read/update the COM port database described below.

According to COM port database:

The system-supplied COM port database arbitrates the use of COM port numbers by COM ports that are installed on the system.

The following code is based on the functionality of the functions listed here (although the usage may be slightly different).

I've performed minor testing on the code in both Windows 7 and Windows 10. Prior to making any registry modifications it's recommended to backup the registry (ie: create a restore point).

The code requires administrative privileges, because it writes to the HKEY_LOCAL_MACHINE registry hive. This can be implemented by adding an "Application Manifest File" to the project and changing:

<requestedExecutionLevel level="asInvoker" uiAccess="false" />

To:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />


Create a class (name: ComDBPortInfo.vb)

Public Class ComDBPortInfo
    Public Property IsReserved As Integer
    Public Property PortName As String
    Public Property PortNumber As Integer
End Class

Create a class (name: MSPortsNetComDBException.vb)

Imports System.Runtime.Serialization

<Serializable>
Public Class MSPortsNetComDBException
    Inherits Exception

    Public Property Value As Integer = 0

    Public Const COULD_NOT_OPEN_HIVE As Integer = 4
    Public Const COULD_NOT_OPEN_SUBKEY As Integer = 5
    Public Const INVALID_BIT_INDEX As Integer = 6
    Public Const INVALID_COMDB_SIZE As Integer = 7
    Public Const INVALID_PORT_NUMBER As Integer = 8
    Public Const PORT_ALREADY_CLAIMED As Integer = 9
    Public Const UNABLE_TO_RESIZE_COMDB As Integer = 10

    Protected Sub New()
        MyBase.New()
    End Sub

    Public Sub New(value As Integer)
        MyBase.New()
        Me.Value = value
    End Sub

    Public Sub New(value As Integer, message As String)
        MyBase.New(message)
        Me.Value = value
    End Sub

    Public Sub New(value As Integer, message As String, innerException As Exception)
        MyBase.New(message, innerException)
        Me.Value = value
    End Sub

    Protected Sub New(info As SerializationInfo, context As StreamingContext)
        MyBase.New(info, context)
    End Sub
End Class

Create a module (name: MSPortsNet.vb)

Imports Microsoft.Win32
Module MSPortsNet

    Public Enum ComDBPortType As Integer
        All = 0
        Available = 1
        Reserved = 2
    End Enum

    'Private Const CDB_REPORT_BITS As Integer = 0
    'Private Const CDB_REPORT_BYTES As Integer = 1

    'if Windows Kit is installed
    'constants can be found in %ProgramFiles(x86)%\Windows Kits\<version>\Include\<version>\um\msports.h
    Private Const COMDB_MIN_PORTS_ARBITRATED As Integer = 256 'minimum COM database size in bits
    Private Const COMDB_MAX_PORTS_ARBITRATED As Integer = 4096 'maximum COM database size in bits

    'if Windows Kit is installed
    'constant can be found in %ProgramFiles(x86)%\Windows Kits\<version>\Include\<version>\shared\winerror.h
    Private Const ERROR_SUCCESS As Integer = 0 'operation successfully completed

    Private Const OPERATION_SUCCESSFUL As Integer = 0 'operation successfully completed

    Public Function ComDBClaimNextFreePort(Optional autoShrink As Boolean = False, Optional regView As RegistryView = RegistryView.Registry64) As Integer
        'get data from COM database
        Dim comDB As Byte() = ComDBGet(regView)

        Dim foundFreeComPort As Boolean = False
        Dim portNumber As Integer = 0
        For i As Integer = 0 To comDB.Length - 1
            For j As Integer = 0 To 7
                'increment
                portNumber  = 1

                'find the first index that has a value of 0
                If GetBitValue(comDB(i), j) = 0 Then
                    'set value
                    foundFreeComPort = True
                    Exit For
                End If
            Next

            If foundFreeComPort Then
                Exit For
            End If
        Next

        If portNumber = 0 Then
            'increment
            portNumber  = 1
        End If
        Return ComDBClaimPort(CInt(portNumber), autoShrink, regView)
    End Function

    Public Function ComDBClaimPort(portNumber As Integer, Optional autoShrink As Boolean = False, Optional regView As RegistryView = RegistryView.Registry64) As Integer
        Return ComDBClaimPort(New List(Of Integer)({portNumber}), autoShrink, regView)
    End Function

    Public Function ComDBClaimPort(portNumbers As List(Of Integer), Optional autoShrink As Boolean = False, Optional regView As RegistryView = RegistryView.Registry64) As Integer
        'get data from COM database
        Dim comDB As Byte() = ComDBGet(regView)

        For Each portNum In portNumbers
            If portNum < 1 Then
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.INVALID_PORT_NUMBER, $"Error (ComDBClaimPort) - Invalid port number. Port number must be > 0 (portNum: {portNum}).")
            End If

            'COM database is stored as REG_BINARY, which is retrieved into a Byte();
            'each bit represents one COM port number starting with 1;
            'index 0 in the Byte() holds data for COM1 - COM8;
            'index 1 in the Byte() holds data for COM9 - COM16; etc...
            'since the data is stored in a Byte(), it's necessary to determine
            'which byte contains the desired data.
            'find which byte contains the appropriate bit; 1 byte = 8 bits
            Dim desiredByteIndex As Integer = CType(Math.Truncate((portNum - 1) / 8), Integer)
            Dim desiredBitIndex As Integer = CType((portNum - 1) Mod 8, Integer)

            'calculate size in bits; 8 bits / 1 byte
            Dim currentComDBSizeInBits As Integer = comDB.Length * 8

            If portNum > currentComDBSizeInBits AndAlso portNum <= COMDB_MAX_PORTS_ARBITRATED Then
                'port number > than what can be stored in the current COMBDB so COMDB needs to be resized
                ComDBResizeDatabase(comDB, portNum, regView)
            ElseIf portNum > currentComDBSizeInBits AndAlso portNum > COMDB_MAX_PORTS_ARBITRATED Then
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.INVALID_PORT_NUMBER, $"Error (ComDBClaimPort) - Invalid port number. The maximum number of ports supported is '{COMDB_MAX_PORTS_ARBITRATED}'. Currently, the COM database holds data for COM ports 1 to {comDB.Length * 8}.")
            End If

            If GetBitValue(comDB(desiredByteIndex), desiredBitIndex) = 1 Then
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.PORT_ALREADY_CLAIMED, $"Error (ComDBClaimPort) - 'COM{portNum}' has already been claimed and is unavailable (portNum: {portNum}). No changes have been made.")
            End If

            'set appropriate bit to claim port
            comDB(desiredByteIndex) = SetBitInByte(comDB(desiredByteIndex), True, desiredBitIndex)
        Next

        If autoShrink Then
            Compact(comDB, regView)
        End If

        'for testing
        'DisplayComPortsByteArray(comDB)

        Dim resultComDBSet = ComDBSet(comDB, regView)

        Return resultComDBSet
    End Function

    Private Function ComDBGet(Optional regView As RegistryView = RegistryView.Registry64) As Byte()
        'get COM database from registry

        Using localKey As RegistryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, regView)
            If localKey IsNot Nothing Then
                Dim comNameArbiterSubkey As String = "System\CurrentControlSet\Control\COM Name Arbiter"

                'open COM Name Arbiter subkey
                Using comNameArbiterKey As RegistryKey = localKey.OpenSubKey(comNameArbiterSubkey, False)
                    If comNameArbiterKey IsNot Nothing Then
                        'read binary data from registry
                        Dim comdb As Byte() = CType(comNameArbiterKey.GetValue("ComDB", Nothing), Byte())
                        Return comdb
                    Else
                        Throw New MSPortsNetComDBException(MSPortsNetComDBException.COULD_NOT_OPEN_SUBKEY, $"Error (ComDBGet) - Could not open '{comNameArbiterSubkey}'")
                    End If
                End Using
            Else
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.COULD_NOT_OPEN_HIVE, $"Error (ComDBGet) - Could Not open 'HKEY_LOCAL_MACHINE' ")
            End If
        End Using
    End Function

    Public Function ComDBGetCurrentPortUsage(Optional regView As RegistryView = RegistryView.Registry64) As List(Of Integer)
        'get COM port usage from COM database

        'COM database is stored as REG_BINARY, which is retrieved into a Byte();
        'each bit represents one COM port number starting with COM1;
        'index 0 in the Byte() holds data for COM1 - COM8;
        'index 1 in the Byte() holds data for COM9 - COM16; etc...
        'below data is converted so that each element of the returned
        'list represents a COM port number (bit representation)
        'Note: the list uses 0-based indices and the first
        'COM port number is 1. Therefore, index 0 = COM1, index 1, = COM2, etc...

        Dim ComDBList As List(Of Integer) = New List(Of Integer)

        Dim ComDB As Byte() = ComDBGet(regView)

        If ComDB IsNot Nothing Then
            'convert to bit array
            Dim ComDBBitArr As BitArray = New BitArray(ComDB)

            For i As Integer = 0 To ComDBBitArr.Length - 1
                'add; 0 = COM1, 1 = COM2, 2 = COM3, ...
                'value of 0 means the port is available
                'value of 1 means the port is unavailable (is reserved)

                If Not ComDBBitArr(i) Then
                    'add; false = 0
                    ComDBList.Add(0)
                Else
                    'add; true = 1
                    ComDBList.Add(1)
                End If
            Next
        End If

        Return ComDBList
    End Function

    Public Function ComDBGetCurrentPortUsage(portType As ComDBPortType, Optional regView As RegistryView = RegistryView.Registry64) As List(Of ComDBPortInfo)
        Dim ComDBList As List(Of Integer) = ComDBGetCurrentPortUsage(regView)
        Dim results As List(Of ComDBPortInfo) = New List(Of ComDBPortInfo)

        If ComDBList IsNot Nothing And ComDBList.Count > 0 Then
            For i As Integer = 0 To ComDBList.Count - 1
                If portType = ComDBPortType.All Then
                    'add
                    results.Add(New ComDBPortInfo() With {.IsReserved = ComDBList(i), .PortName = $"COM{i   1}", .PortNumber = i   1})
                ElseIf portType = ComDBPortType.Available AndAlso ComDBList(i) = 0 Then
                    'add
                    results.Add(New ComDBPortInfo() With {.IsReserved = ComDBList(i), .PortName = $"COM{i   1}", .PortNumber = i   1})
                ElseIf portType = ComDBPortType.Reserved AndAlso ComDBList(i) = 1 Then
                    'add
                    results.Add(New ComDBPortInfo() With {.IsReserved = ComDBList(i), .PortName = $"COM{i   1}", .PortNumber = i   1})
                End If
            Next
        End If

        Return results
    End Function

    Public Function ComDBReleasePort(portNumber As Integer, Optional autoShrink As Boolean = False, Optional regView As RegistryView = RegistryView.Registry64) As Integer
        Return ComDBReleasePort(New List(Of Integer)({portNumber}), autoShrink, regView)
    End Function
    Public Function ComDBReleasePort(portNumbers As List(Of Integer), Optional autoShrink As Boolean = False, Optional regView As RegistryView = RegistryView.Registry64) As Integer
        'get data from COM database
        Dim comDB As Byte() = ComDBGet(regView)

        For Each portNum In portNumbers
            If portNum < 1 Then
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.INVALID_PORT_NUMBER, $"Error (ComDBReleasePort) - Invalid port number. Port number must be > 0 (portNumber: {portNum}).")
            End If

            If portNum > comDB.Length * 8 Then
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.INVALID_PORT_NUMBER, $"Error (ComDBReleasePort) - Invalid port number. Port number must be > 0 and < {comDB.Length * 8} which is the last port number currently stored in the database (portNumber: {portNum}).")
            End If

            'find which byte contains the appropriate bit
            '8 bits per 1 byte
            Dim desiredByteIndex As Integer = CType(Math.Truncate((portNum - 1) / 8), Integer)
            Dim desiredBitIndex As Integer = CType((portNum - 1) Mod 8, Integer)

            If GetBitValue(comDB(desiredByteIndex), desiredBitIndex) = 0 Then
                Debug.WriteLine($"Info (ComDBReleasePort) - 'COM{portNum}' is currently available. Skipping")
                Return OPERATION_SUCCESSFUL
            End If

            'set appropriate bit to claim port
            comDB(desiredByteIndex) = SetBitInByte(comDB(desiredByteIndex), False, desiredBitIndex)
        Next

        If autoShrink Then
            Compact(comDB, regView)
        End If

        'for testing
        'DisplayComPortsByteArray(comDB)

        'save COMDB
        Dim resultComDBSet = ComDBSet(comDB, regView)

        Return resultComDBSet
    End Function

    Private Function ComDBResizeDatabaseByDesiredIndex(comDB As Byte(), lastByteIndexContainingData As Integer, Optional regView As RegistryView = RegistryView.Registry64) As Byte()
        'since a Byte() is being used, it's not necessary to
        'determine the actual port number, but rather just the byte index
        'that contains the bit which represents the port number;
        '8 bits in a byte; to dertermine the first port number represented
        'within the byte, multiply the byte index by 8
        Return ComDBResizeDatabase(comDB, lastByteIndexContainingData * 8, regView)
    End Function
    Private Function ComDBResizeDatabase(comDB As Byte(), lastPortNumberNeedingReservation As Integer, Optional regView As RegistryView = RegistryView.Registry64) As Byte()
        'new size must be >= COMDB_MIN_PORTS_ARBITRATED and <= COMDB_MAX_PORTS_ARBITRATED

        'calculate minimum Byte() size
        Dim minArraySize As Integer = CType(COMDB_MIN_PORTS_ARBITRATED / 8, Integer)

        'calculate maximum Byte() size
        Dim maxArraySize As Integer = CType(COMDB_MAX_PORTS_ARBITRATED / 8, Integer)

        'calculate the size
        Dim comDBSizeIncrement As Integer = CType(1024 / 8, Integer)

        'COMDB is stored as REG_BINARY, which is retrieved into a Byte();
        'each bit represents one COM port number starting with 1;
        'index 0 in the Byte() holds data for COM1 - COM8;
        'index 1 in the Byte() holds data for COM9 - COM16; etc...
        'since the data is stored in a Byte(), it's necessary to determine
        'which byte contains the desired data.
        'find which byte contains the appropriate bit; 1 byte = 8 bits
        Dim desiredByteIndex As Integer = CType(Math.Truncate((lastPortNumberNeedingReservation - 1) / 8), Integer)

        'set value; size = index   1
        Dim newArraySize As Integer = desiredByteIndex   1

        'to ensure that COMDB is only resized by comDBSizeIncrement
        'calculate the appropriate size
        While CType(newArraySize * 8, Integer) < lastPortNumberNeedingReservation AndAlso newArraySize <= COMDB_MAX_PORTS_ARBITRATED
            'increase size
            newArraySize  = comDBSizeIncrement
        End While

        If newArraySize > comDB.Length Then
            'resize Byte()
            Array.Resize(Of Byte)(comDB, newArraySize)
        Else
            'ensure that Byte array isn't resized below where data exists
            Dim lastByteIndexContainingData As Integer = GetLastByteIndexContainingData(comDB)
            'Debug.WriteLine($"lastByteIndexContainingData: {lastByteIndexContainingData}")

            If lastByteIndexContainingData > newArraySize Then
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.UNABLE_TO_RESIZE_COMDB, "Error (ComDBResizeDatabase) - Resizing the COM database To length '{newArraySize}' would result in a loss of data, so it can't be performed. Releasing reserved COM ports prior to resizing the COM database may allow it to be shrunk. Ensure that the registry has been backed up (ie: create a restore point) before releasing reserved COM ports. (lastByteIndexContainingData: {lastByteIndexContainingData})")
            End If

            'use a list so it's resized automatically
            Dim tempComDBList As List(Of Byte) = New List(Of Byte)

            For i As Integer = 0 To lastByteIndexContainingData
                'add
                tempComDBList.Add(comDB(i))
            Next

            'set value
            comDB = tempComDBList.ToArray()

            'resize so the ComDB is an increment of comDBSizeIncrement
            Array.Resize(comDB, newArraySize)
        End If

        Return comDB
    End Function
    Private Function ComDBSet(comDB As Byte(), Optional regView As RegistryView = RegistryView.Registry64) As Integer
        'this method requires administrative privileges because it
        'writes to the HKEY_LOCAL_MACHINE registry hive

        Using localKey As RegistryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, regView)
            If localKey IsNot Nothing Then
                Dim comNameArbiterSubkey As String = "System\CurrentControlSet\Control\COM Name Arbiter"

                'open COM Name Arbiter subkey
                Using comNameArbiterKey As RegistryKey = localKey.OpenSubKey(comNameArbiterSubkey, True)
                    If comNameArbiterKey IsNot Nothing Then
                        'save binary data to registry
                        comNameArbiterKey.SetValue("ComDB", comDB, RegistryValueKind.Binary)
                    Else
                        Throw New MSPortsNetComDBException(MSPortsNetComDBException.COULD_NOT_OPEN_SUBKEY, $"Error (ComDBSet) - Could not open '{comNameArbiterSubkey}'")
                    End If
                End Using
            Else
                Throw New MSPortsNetComDBException(MSPortsNetComDBException.COULD_NOT_OPEN_HIVE, $"Error (ComDBSet) - Could Not open 'HKEY_LOCAL_MACHINE' ")
            End If
        End Using

        'operation successfully completed
        Return OPERATION_SUCCESSFUL
    End Function

    Private Function Compact(comDB As Byte(), Optional regView As RegistryView = RegistryView.Registry64) As Byte()
        'if able, shrinks the size of the COM database ensuring that no bytes with a bit set to 1 are deleted

        Dim lastByteIndexContainingData As Integer = GetLastByteIndexContainingData(comDB)
        Return ComDBResizeDatabaseByDesiredIndex(comDB, lastByteIndexContainingData, regView)
    End Function

    Public Sub DisplayComPorts(Optional regView As RegistryView = RegistryView.Registry64)
        'this method is used for testing; it outputs COM port usage as stored in the COM database
        Dim ports As List(Of Integer) = ComDBGetCurrentPortUsage()

        If ports IsNot Nothing Then
            For i As Integer = 0 To ports.Count - 1
                Dim comPortName As String = $"COM{i   1}"
                Dim isReserved As Integer = ports(i)
                Debug.WriteLine($"{comPortName}: {isReserved.ToString()}")
            Next
        End If
    End Sub

    Private Sub DisplayComPortsByteArray(comDB As Byte())
        'this method is used for testing; it outputs COM port usage as stored in the Byte();
        'this information may differ from what's in the COM port database, if the data
        'has been modified, but not yet saved

        If comDB IsNot Nothing Then
            'convert to bit array
            Dim ComDBBitArr As BitArray = New BitArray(comDB)

            Dim byteArrayIndex As Integer = 0
            Debug.WriteLine($"Index: {byteArrayIndex}")

            For i As Integer = 0 To ComDBBitArr.Length - 1
                Dim isReserved As Integer = 0

                If ComDBBitArr(i) Then
                    'set value
                    isReserved = 1
                End If

                Debug.WriteLine($"    COM{i   1}: {isReserved}")

                If (i   1) Mod 8 = 0 Then
                    'increment
                    byteArrayIndex  = 1

                    Debug.WriteLine($"Index: {byteArrayIndex}")
                End If
            Next
        End If
    End Sub

    Private Function GetBitValue(b As Byte, bitIndex As Integer) As Byte
        'get bit value from byte

        If bitIndex < 0 OrElse bitIndex > 7 Then
            Throw New MSPortsNetComDBException(MSPortsNetComDBException.INVALID_BIT_INDEX, $"Error (GetBitValue) - Invalid bit index. Value must be 0 to 7 (bitIndex: {bitIndex})")
        End If

        'result: The result of shifting the bit pattern. The data type is the same as that of pattern.
        'pattern: is bit pattern to be shifted; The data type must be an integral type (SByte, Byte, Short, UShort, Integer, UInteger, Long, or ULong)
        'amount: The number of bits to shift the bit pattern. The data type must be Integer or widen to Integer.
        '
        'for bit shifting: result = pattern >> amount
        'after bit-shifting is complete, the desired value is
        'found by performing a logical AND with 1 (on the result)
        Return CType((b >> bitIndex) And 1, Byte)
    End Function

    Private Function GetLastByteIndexContainingData(comDB As Byte()) As Integer
        'find the last index of the Byte array that has any bit set to 1

        Dim lastByteIndexContainingData As Integer = 0

        For i As Integer = 0 To comDB.Length - 1
            For j As Integer = 0 To 7
                'check each bit to see if value is set to 1
                If GetBitValue(comDB(i), j) = 1 Then
                    'if value set to 1, save the index
                    lastByteIndexContainingData = i
                End If
            Next
        Next

        Return lastByteIndexContainingData
    End Function

    Private Function SetBitInByte(b As Byte, isReserved As Boolean, bitIndex As Integer) As Byte
        'use a mask to set the value of the desired bit within a Byte

        If bitIndex < 0 OrElse bitIndex > 7 Then
            Throw New MSPortsNetComDBException(MSPortsNetComDBException.INVALID_BIT_INDEX, $"Error (SetBitInByte) - Invalid bit index. Value must be 0 to 7 (bitIndex: {bitIndex})")
        End If

        'get index
        Dim bitIndexInByte As Integer = bitIndex Mod 8

        'result: The result of shifting the bit pattern. The data type is the same as that of pattern.
        'pattern: is bit pattern to be shifted; The data type must be an integral type (SByte, Byte, Short, UShort, Integer, UInteger, Long, or ULong)
        'amount: The number of bits to shift the bit pattern. The data type must be Integer or widen to Integer.
        '
        'for bit shifting: result = pattern << amount
        'this value will is used with logical operations below
        Dim mask As Byte = CType((1 << bitIndexInByte), Byte)

        If isReserved Then
            'bit is set by performing a logical OR with mask value
            Return b Or mask
        Else
            'clear the value; C#, ~ instead of Not
            'bit is set by performing a logical AND with the complement
            'of the mask value. in VB.NET, Not is used to get the complement
            'in C#, '~' is used to get the complement instead of 'Not'.
            'instead of using the complement, one could
            'create another mask that shifts '0' to the left (instead of '1')
            Return b And (Not mask)
        End If
    End Function
End Module

Usage: ComDBClaimNextFreePort

'claim next available COM port
Dim result As Integer = MSPortsNet.ComDBClaimNextFreePort()
'Dim result As Integer = MSPortsNet.ComDBClaimNextFreePort(True)

Usage: ComDBClaimPort

'claim one COM port
Dim resultSinglePort As Integer = MSPortsNet.ComDBClaimPort(4)
'Dim resultSinglePort As Integer = MSPortsNet.ComDBClaimPort(4, True)

Usage: ComDBClaimPort (multiple port numbers)

'claim multiple COM ports
Dim resultMultiplePorts As Integer = MSPorts.ComDBClaimPort(New List(Of Integer)({18, 19}))
'Dim resultMultiplePorts As Integer = MSPorts.ComDBClaimPort(New List(Of Integer)({18, 19}), True)

Usage: ComDBGetCurrentPortUsage

'get all COM ports in database
Dim portsAll As List(Of ComDBPortInfo) = ComDBGetCurrentPortUsage(ComDBPortType.All)

'get all available COM ports in database
Dim portsAvailable As List(Of ComDBPortInfo) = ComDBGetCurrentPortUsage(ComDBPortType.Available)

'get all reserved COM ports in database
Dim portsReserved As List(Of ComDBPortInfo) = ComDBGetCurrentPortUsage(ComDBPortType.Reserved)

Usage: ComDBReleasePort

'release one COM port
Dim resultSinglePort As Integer = MSPortsNet.ComDBReleasePort(18)
'Dim resultSinglePort As Integer = MSPortsNet.ComDBReleasePort(18, True)

Usage: ComDBReleasePort (multiple port numbers)

'release multiple COM ports
Dim resultMultiplePorts As Integer = MSPorts.ComDBReleasePort(New List(Of Integer)({18, 19}))
'Dim resultMultiplePorts As Integer = MSPorts.ComDBReleasePort(New List(Of Integer)({18, 19}), True)

Additional Resources

  • Related