Serial Port – Enumeración & Disponibilidad

 

         Saber sobre la disponibilidad de nuestros puertos serie antes de su selección en un combobox.

  How to know about availability of our computer serial ports before select one from a combo box.

A menudo las aplicaciones que requieren seleccionar un dispositivo antes de efectuar algún tipo de comunicacion, no ofrecen ninguna información adicional sobre el estado del dispositivo. Sobre todo si hablamos del puerto serie, normalmente nos ofrecen una simple enumeración de los COM. Esto último es el causante de que la aplicación nos permita seleccionar un puerto que en ocasiones no existe o está siendo usado por otro programa.

Os propongo una idea con la intención de mejorar y facilitar la selección de este tipo de dispositivos en nuestras aplicaciones.

Básicamente se trata de enumerar en un ‘ComboBox’ personalizado los puertos existentes en nuestro equipo, utilizando el mandato :

My.Computer.Ports.SerialPortNames.ToArray

En el momento de la inicialización del ‘combobox’ asignaremos el evento de ‘DrawItem’ a la función que enriquecerá el aspecto, añadiendo al nombre un rectángulo coloreado y el texto correspondiente a la disponibilidad del puerto.

AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status

No dudéis en contactar conmigo si necesitáis aclarar o necesitáis entender alguna parte del código.

Para poder darle mayor difusión los comentarios del código están en inglés, aunque si os parece oportuno y necesario puedo posteároslo también en español.

Sometimes our communications applications are required to select any type of external device, and normally these applications are not giving any extra information about their availability. This is the case when talk around serial ports, normally when select the port only have a simple enumeration of COM’s, this may be confusing at time leaving at users selecting inexistent ports or ports that simply are already in use.

With this sample, you can improve and make easy these device selections in our applications.

The main think is enumerate serial port inside our customized ‘ComboBox’, using :

My.Computer.Ports.SerialPortNames.ToArray

After when initialize our combo only need assign ‘DrawItem’ event to function with our personalized combo draw,

AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status

This function are adding red rectangle and “busy” text when no have availability, and green rectangle and “available” text when the port is free.

Please no doubt in contact with me if you need any other explanation or opinion about this.

 

 SerialEnum_Es

SerialEnum_en 

 

Public Class Form1
    ‘Enumerate Serial Ports on Machine
    ‘Get Serial Port availability

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ‘Just drag & drop combobox from toolbox to form designer
        Me.ComboBox1.DrawMode = DrawMode.OwnerDrawVariable                     ‘select my own drag mode
        Me.ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList                ‘aspect when drop down
        Me.ComboBox1.DataSource = My.Computer.Ports.SerialPortNames.ToArray    ‘enumerate serialports
        Me.ComboBox1.TabIndex = 0                                              ‘select first tabindex
        AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status       ‘draw my personal cmbo
    End Sub
   
    ‘ Draw our custom combo
    Private Sub cmbo_SerialPorts_Status( _
        ByVal sender As Object, _
        ByVal CmboItem As System.Windows.Forms.DrawItemEventArgs)

        ‘ Draw the background of the item.
        CmboItem.DrawBackground()
       
        ‘Default Values if port is available
        Dim status As String = “Available”
        Dim brush As New SolidBrush(Color.Green)
        Dim font As System.Drawing.Font = Me.Font
        Dim fontbrush As Brush = Brushes.Black
        Dim rectangle As Rectangle = New  _
            Rectangle(2, CmboItem.Bounds.Top + 2, _
                         CmboItem.Bounds.Height, _
                         CmboItem.Bounds.Height – 4)
       
        ‘Check for port availability
        Try
            ‘ If port open & close with no exception
            ‘ draw the item with default font and green rectangle
            Dim PortTest As New System.IO.Ports.SerialPort
            PortTest = My.Computer.Ports.OpenSerialPort(My.Computer.Ports.SerialPortNames(CmboItem.Index))
            PortTest.Close()
        Catch ex As Exception
            ‘ If port is not available
            ‘ draw the item with italic & strikeout font and red rectangle
            brush = New SolidBrush(Color.Red)
            status = “In Use”
            font = New Font(FontFamily.GenericSansSerif, Me.Font.Size, FontStyle.Italic Xor FontStyle.Strikeout)
            fontbrush = Brushes.DimGray
        End Try

        ‘fill combo item rectangle
        CmboItem.Graphics.FillRectangle(brush, rectangle)
        ‘write text with actual port status for this item
        CmboItem.Graphics.DrawString( _
            My.Computer.Ports.SerialPortNames(CmboItem.Index) + ” – “ + status, _
            font, _
            fontbrush, _
            New  _
                    RectangleF(CmboItem.Bounds.X + rectangle.Width, _
                               CmboItem.Bounds.Y, _
                               CmboItem.Bounds.Width, _
                               CmboItem.Bounds.Height) _
        )
        ‘ Draw focus rectangle when mouse are over an item.
        CmboItem.DrawFocusRectangle()
    End Sub
End
Class

23 thoughts on “Serial Port – Enumeración & Disponibilidad”

  1. Hola Pep, es realmente útil saber si el puerto esta disponible. Un ejemplo muy interesante. Gracias.

    Offtopic: por cierto, continua activo el grupo SpainNet? He intentado acceder a la web pero no esta disponible. Saludos!

  2. Hola Ivan!!

    Pues ciertamente es util y sobretodo facilita la seleccion de los puertos a los usuarios que no quieren entrar en la administracion de dispositivos para saber si existe el com o no.

    Tambien como sabes el puerto puede no tener ningun dispositivo fisicamente enchufado, pero quizas este ocupado por alguna otra aplicacion :-)

    En tanto a SpainNet, por supuesto que sigue vivo y coleando, lo que ocurre es que nos quedamos sin servidor propio. Aunque puedes seguir nuestras actividades en :

    http://www.codezone.com/UserGroupInformation.CodezoneCom?ActiveID=3498

    Saludos y gracias por el interes.

  3. Hola,

    Muy interesante!!! pero estoy intentado pasarlo a c# y tengo algunos problemas con la transformación… podrías ponerlo en c# también?

    Moltes gràcies…
    mtz

  4. Hola Mtz…
    Podrias indicarme la parte donde tienes problemas para pasarlo a C#… puedes contactar conmigo a traves de [Contact] en la parte superior derecha del Blog.

    Espero tus noticias,
    Pep Lluis,

  5. HOLA PEPELLUIS QUIERO HACER ALGO PARECIDO PERO NO TENGO DISPONIBLE LO DEL
    My.Computer.Ports.SerialPortNames.ToArray
    ES QUE YO TENGO .NET Y NO ESTA O NECESITO IMPORTAR HERRAMIENTAS EXTRAS

  6. Hola Mariano,
    En principio ‘My’ esta disponible en Visual Studio como espacio de nombres, la unica duda es saber si estas utilizando VB y quizas la version ‘Express’.

    De todas formas dispones de la expresion :
    Dim EnumeracionPuertos As New ComboBox
    EnumeracionPuertos.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames.ToArray)

    Si estas utilizando C#, puedes leerte este post:
    http://msmvps.com/blogs/peplluis/archive/2009/03/16/como-enumerar-los-com-s-de-nuestro-equipo-en-vb-y-en-c.aspx

    Saludos,
    Pep Lluis,

  7. Amigo Pep Lluis, necesito rediccionar un puerto serie, pues al ejecutar un programa antiguo msdos me dice “El sistema no puede abrir el puerto com3 requerido por la aplicación”… lo cierto, es que me da la opción cerrar ó omitir, si lo omito en realidad funciona bien, pero con el com1 que es el que tengo habilitado (he probado cambiar en windows com3, y ahora me dice que no puede conectar con el com1 ¡vaya lio!), ¿que tengo que hacer, ¿podrias ayudarme? Te lo agradezco muchisimo…. ma_emilio@hotmail.com gracias

  8. Hola Emilio,
    Puedes contactar conmigo a traves de la opcion [Contac] en la parte superior izquierda de esta pagina.

    Lo que necesitaria saber es como estas utilizando tu aplicacion en MSDOS o Windows… y en todo caso, porque MSDOS y Windows?

    Espero tus noticias,
    Pep Lluis,

  9. Saludos.

    Felicidades por esta aportacion, es bastante buena. Quiero recalcar que este tipo de aportaciones nos sacan de apuros a muchos novatillos.
    Solo tengo una pregunta: Existe alguna forma de modificar el codigo para saber no solamente si esta en uso el puerto sino tambien que aplicacion lo esta utilizando??

    De antemano gracias por tomarse el tiempo de contestar. Buen dia.

  10. Jorge!
    Pues la verdad… es una pregunta muy buena e interesante, lo cierto es que desde ‘management’ puedes inventariar el hardware, pero desconozco de que lugar del sistema puedes extraer la lista de quien tiene cedidos los recursos.

    Lo tendre en mente y si localizo como hacerlo lo compartire con todos vosotros, de otra forma si averiguas tambien me gustara saberlo.

    Gracias por la pregunta.
    Saludos,
    Pep Lluis,

  11. Pep; a qué se debe que al compilar el código me arroja un error en:
    New _
    RectangleF(CmboItem.Bounds.X + rectangle.Width, _
    CmboItem.Bounds.Y, _
    CmboItem.Bounds.Width, _
    CmboItem.Bounds.Height) _
    )

    Me dice que el índice está fuera de intervalo; salu2

  12. Hola Javier,
    Mira de ejecutar la instruccion completa en una sola linea (Sin bajo guiones)

    CmboItem.Graphics.DrawString(My.Computer.Ports.SerialPortNames(CmboItem.Index) + ” – ” + status, font, fontbrush, New RectangleF(CmboItem.Bounds.X + rectangle.Width,CmboItem.Bounds.Y, CmboItem.Bounds.Width, CmboItem.Bounds.Height))

    Espero que asi funcione,
    Pep Lluis,

  13. Hola Pep, estaba viendo tu ejemplo y me parece interesante. Pero fijate que también me tira el mismo error que a Javier, y veo q el problema no está en poner o no en una sola línea el código q le sugeriste a él. Dime algo, que tamaño (Height y Width) le has definido al ComboBox1?

  14. Hola Douglas,
    Para provar este ejemplo, es necesario crear un nuevo proyecto “windows forms” añadir un Combobox desde el cuadro de herramientas, copiar y pegar el codigo de este ejemplo y listo.

    Esta verificado usando visual Studio 2008… recuerda que debeis arrastrar y soltar el combobox al form de vuestra aplicacion, puede que sea ese el detalle.

    Si aun asi no os funciona comunicate conmigo a traves de [contact] y te mando el proyecto en .zip.
    Saludos,
    Pep Lluis,

  15. Hola de nuevo Pep,

    Gracias por responder tan rápido. Fíjate que encontré el problema, y era que yo lo estaba probando en Visual Studio 2005 y está hecho para que corra perfectamente como tú lo dijiste en 2008. El único cambio que le hice fue que en la línea Me.ComboBox1.DataSource = My.Computer.Ports.SerialPortNames.ToArray que es la que llena el combo, le quité el ToArray y listo!!

    Te lo informo para que lo sepas y por si algún otro visita tu página que me imagino que seguro lo harán y tiene la misma dificultad, pues que conozca la solución!!!

    Saludos,

  16. Muy buen dia, gusto de saludarte, muy interesante este ejemplo, solo con un favor, como puedo saber la descripcion del dispositivo que esta en el puerto. gracias

  17. Hola Mario,
    Los puertos serie no pueden enumerar los dispositivos conectados a ellos. Solo en caso de conocer de antemano que tipo de disposivo esta conectado, nuestra aplicacion puede interrogarlo para saber cosas sobre el. A nivel de protocolo no existen descriptores genericos.

    Saludos,
    PepLluis,

  18. Excelente tu espiritu solidario y el dseo de compartir con otros tu conocmieto.

    Realmente eso hace creser mas a un a las personas d bien.

    Gracias de antemano.

    Conoces si existe la forma de que en ves d que apareca COM1, Com2 …. Aparezca el nombre que sale en el administrador de dispositivos ?

    en el listado  de los puertos… alg asi como, puerto de comunicaciones xxxxx,, con el objetivo de que cuando insertemos un cable usb a Rs32 aparezca el Nombre del Cable y as conocer con mas presicion cual es el puerto qeu estaremos utilizando.

     

  19. Hola buena noche.
    Esta es la cuarta ves qeu te escribo buscando a misma situacón, pero nunca he podido ver una respuesta, ni en el foro nien el correo.
    Posiblemente no lo he estado haciendo correctamente pero lo voy a intentar otra ves mas.

    ¿Enumerar los puertos con el api del Setupapi.dll para obtener el nombre descriptivo d lospuertos como aparecen en el Administrador de dispositivos.?

  20. Hola Nico,
    Lamento que no encuentres la respuesta, pero respondi a Mario con la misma pregunta mas arriba, como bien sabes el los foros son el sitio adecuado para plantear preguntas i obtener respuestas pues existen un monton de expertos atentos a responder las preguntas sobre cada tema. Lamento no poder ayudarte con el api Setupapi.dll pues no esta en el rango de mi experiencia. Te animos a que lo vuelvas a intentar en los foros.

    Gracias por tu compresion,
    PepLluis,

  21. Es posible hace lo mismo pero , web (VB) , yo contrui el codigo , pero al ponerlo en un servidor WEB , claramente me dice que el puerto no esta ya que el dispositovo lo tento conectado en mi PC y no en el servidor WEb.

    Alguna idea ?

    Saludos.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>