This example extends the previous Threading example. The main difference is that here the program attempts to detect the VCP Wiring is connected to by examining the instanceNames returned from querying MSSerial_PortName. If no match is found then the user is prompted to enter a portName.

Additionally this class uses a separate CommandLine.Utility namespace. This allows the application to be passed a com port name, to circumvent the auto searching, or alternatively a 'driverId' should FTDI's VCP driver details change in the future.

For example:
WiringAutoChat.exe /port=COM1
WiringAutoChat.exe /id=ASUSBUS


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* WiringAutoChat - Version 1.0
*
* By: Fraser [please] Chapman [no] gmail [spam] com
*
* Notes:
* Automatically connects a Serial port resource to the Virtual COM port
* Swaped (.NET) SerialPort.GetPortNames() for (WMI) MSSerial_PortName
* Cleaned up the thread closure / application exit.
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

//Standard console namespace
using System;
//Namespaces for this example
using System.IO.Ports;
using System.Threading;
using System.Management;
using CommandLine.Utility;

namespace WiringAutoChat
{
  class WiringAutoChat
  {
    // default ID for (VCP) drivers http://www.ftdichip.com/Drivers/VCP.htm
    static string _driverId = "FTDI";

    static bool _continue;
    static SerialPort _serialPort;

    // Output strings
    static string _os_looking = "Looking for " + _driverId + "...";
    static string _os_error = "Error";
    static string _os_connected = "Connected";
    static string _os_exit = "EXIT";
    static string _os_enter = "Enter text to send, " + _os_exit + " quits:";
  static string _os_found = "Found";
    static string _os_notfound = "Couldn't find wiring using";
    static string _os_selectport = "Please select a port. ie:";
    static string _os_returned = "Wiring says";

    ///
    /// Entry point
    ///
    /// array of commad line arguments
    static void Main(string[] args)
    {
      Arguments myarg = new Arguments(args);
      Thread readThread = new Thread(Read);
      _serialPort = new SerialPort();

      //if a driver id is passed in the command line arguments then use it.
      if (myarg["id"] != null)
      {
        _driverId = myarg["id"];
      }

      //if a valid COM port is passed in the command line arguments then use it.
      if (myarg["port"] != null && myarg["port"].StartsWith("COM"))
      {
        _serialPort.PortName = myarg["port"];
      }
      else
      {
        // Otherwise we automaticaly try to find Wiring using _driverId
        string wiringSerial = GetWiringSerial();
        if (wiringSerial != String.Empty)
        {
          _serialPort.PortName = wiringSerial;
        }
        else
        // if we can't find it automatically ask user to enter a port name
        {
          _serialPort.PortName = SetPortName();
        }
      }

      //Wiring settings
      _serialPort.BaudRate = 9600;
      _serialPort.Parity = Parity.None;
      _serialPort.DataBits = 8;
      _serialPort.StopBits = StopBits.One;

      try
      {
        _serialPort.Open();
      }
      catch (Exception e)
      {
        Console.WriteLine("| * {0}: {1}", _os_error, e.Message);
      }

      if (_serialPort.IsOpen)
      {
        Console.WriteLine("| {0} {1}", _os_connected, _serialPort.PortName);
        Console.WriteLine("| {0}{1}", _os_enter, Environment.NewLine);
        // continue to check and send messages until user sends _os_exit's value
        _continue = true;
        readThread.Start();
        Write();
      }

      if (!readThread.Join(100))
        readThread.Abort();

      if(_serialPort.IsOpen)
        _serialPort.Close();

      Environment.Exit(0);
    }

    ///
    /// Writes the input line of text to wiring, checks for _os_exit
    ///
    private static void Write()
    {
      StringComparer sc = StringComparer.Ordinal;
      string m;

      while (_continue)
      {
        m = Console.ReadLine();
        
        if (sc.Equals(_os_exit, m))
        {
          _continue = false;
        }
        else
        {
          _serialPort.WriteLine(m);
        }
      }
    }

    ///
    /// Reads any incomming messages from wiring and outputs them in the conole
    ///
    private static void Read()
    {
      string m = String.Empty;

      while (_continue)
      {
        try
        {
          m = _serialPort.ReadLine();
        }
        catch (Exception e) { }

        if (m != String.Empty)
        {
          Console.WriteLine("| {0} > "{1}"", _os_returned, m);
        }
      }
    }

    ///
    /// Attempts to find a COM port InstanceName that starts with _driverId
    /// ie. (FTDIBUSVID_0000+PID_0000+0&0000000&0&0?000_0) (FTDI)
    ///
    /// The matching COM port name or an empty string
    private static string GetWiringSerial()
    {
      Console.WriteLine("| {0}", _os_looking);
      string wiringPort = String.Empty;

      try
      {
        ManagementObjectSearcher mos =
          new ManagementObjectSearcher("rootWMI",
          "SELECT InstanceName, PortName FROM MSSerial_PortName");
        
        foreach (ManagementObject mo in mos.Get())
        {
          //Console.WriteLine("| {0}:{1}", mo["PortName"], mo["InstanceName"]);
          
          if (mo["InstanceName"].ToString().StartsWith(_driverId))
          {
            Console.WriteLine("| {0} {1} - {2}", _os_found, mo["InstanceName"], mo["PortName"]);
            return (string)mo["PortName"];
          }
        }
      }
      catch (ManagementException me)
      {
        Console.WriteLine("| * WMI {0}: {1}", _os_error, me.Message);
      }

      return wiringPort;
    }

    ///
    /// Promts the user for a port name
    ///
    /// A valid COM port name
    private static string SetPortName()
    {
      Console.WriteLine("| {0} - {1}", _os_notfound, _driverId);
      Console.WriteLine("| {0}({1}):", _os_selectport, _serialPort.PortName);

      string portName = Console.ReadLine();

      if (!portName.StartsWith("COM"))
      {
        portName = _serialPort.PortName;
      }

      return portName;
    }

  }
}

This example extends the previous Threading example. The main difference is that here the program attempts to detect the VCP Wiring is connected to by examining the instanceNames returned from querying MSSerial_PortName. If no match is found then the user is prompted to enter a portName.

Additionally this class uses a separate CommandLine.Utility namespace. This allows the application to be passed a com port name, to circumvent the auto searching, or alternatively a 'driverId' should FTDI's VCP driver details change in the future.

For example:
WiringAutoChat.exe /port=COM1
WiringAutoChat.exe /id=ASUSBUS


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* WiringAutoChat - Version 1.0
*
* By: Fraser [please] Chapman [no] gmail [spam] com
*
* Notes:
* Automatically connects a Serial port resource to the Virtual COM port
* Swaped (.NET) SerialPort.GetPortNames() for (WMI) MSSerial_PortName
* Cleaned up the thread closure / application exit.
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

//Standard console namespace
using System;
//Namespaces for this example
using System.IO.Ports;
using System.Threading;
using System.Management;
using CommandLine.Utility;

namespace WiringAutoChat
{
  class WiringAutoChat
  {
    // default ID for (VCP) drivers http://www.ftdichip.com/Drivers/VCP.htm
    static string _driverId = "FTDI";

    static bool _continue;
    static SerialPort _serialPort;

    // Output strings
    static string _os_looking = "Looking for " + _driverId + "...";
    static string _os_error = "Error";
    static string _os_connected = "Connected";
    static string _os_exit = "EXIT";
    static string _os_enter = "Enter text to send, " + _os_exit + " quits:";
  static string _os_found = "Found";
    static string _os_notfound = "Couldn't find wiring using";
    static string _os_selectport = "Please select a port. ie:";
    static string _os_returned = "Wiring says";

    ///
    /// Entry point
    ///
    /// array of commad line arguments
    static void Main(string[] args)
    {
      Arguments myarg = new Arguments(args);
      Thread readThread = new Thread(Read);
      _serialPort = new SerialPort();

      //if a driver id is passed in the command line arguments then use it.
      if (myarg["id"] != null)
      {
        _driverId = myarg["id"];
      }

      //if a valid COM port is passed in the command line arguments then use it.
      if (myarg["port"] != null && myarg["port"].StartsWith("COM"))
      {
        _serialPort.PortName = myarg["port"];
      }
      else
      {
        // Otherwise we automaticaly try to find Wiring using _driverId
        string wiringSerial = GetWiringSerial();
        if (wiringSerial != String.Empty)
        {
          _serialPort.PortName = wiringSerial;
        }
        else
        // if we can't find it automatically ask user to enter a port name
        {
          _serialPort.PortName = SetPortName();
        }
      }

      //Wiring settings
      _serialPort.BaudRate = 9600;
      _serialPort.Parity = Parity.None;
      _serialPort.DataBits = 8;
      _serialPort.StopBits = StopBits.One;

      try
      {
        _serialPort.Open();
      }
      catch (Exception e)
      {
        Console.WriteLine("| * {0}: {1}", _os_error, e.Message);
      }

      if (_serialPort.IsOpen)
      {
        Console.WriteLine("| {0} {1}", _os_connected, _serialPort.PortName);
        Console.WriteLine("| {0}{1}", _os_enter, Environment.NewLine);
        // continue to check and send messages until user sends _os_exit's value
        _continue = true;
        readThread.Start();
        Write();
      }

      if (!readThread.Join(100))
        readThread.Abort();

      if(_serialPort.IsOpen)
        _serialPort.Close();

      Environment.Exit(0);
    }

    ///
    /// Writes the input line of text to wiring, checks for _os_exit
    ///
    private static void Write()
    {
      StringComparer sc = StringComparer.Ordinal;
      string m;

      while (_continue)
      {
        m = Console.ReadLine();
        
        if (sc.Equals(_os_exit, m))
        {
          _continue = false;
        }
        else
        {
          _serialPort.WriteLine(m);
        }
      }
    }

    ///
    /// Reads any incomming messages from wiring and outputs them in the conole
    ///
    private static void Read()
    {
      string m = String.Empty;

      while (_continue)
      {
        try
        {
          m = _serialPort.ReadLine();
        }
        catch (Exception e) { }

        if (m != String.Empty)
        {
          Console.WriteLine("| {0} > "{1}"", _os_returned, m);
        }
      }
    }

    ///
    /// Attempts to find a COM port InstanceName that starts with _driverId
    /// ie. (FTDIBUSVID_0000+PID_0000+0&0000000&0&0?000_0) (FTDI)
    ///
    /// The matching COM port name or an empty string
    private static string GetWiringSerial()
    {
      Console.WriteLine("| {0}", _os_looking);
      string wiringPort = String.Empty;

      try
      {
        ManagementObjectSearcher mos =
          new ManagementObjectSearcher("rootWMI",
          "SELECT InstanceName, PortName FROM MSSerial_PortName");
        
        foreach (ManagementObject mo in mos.Get())
        {
          //Console.WriteLine("| {0}:{1}", mo["PortName"], mo["InstanceName"]);
          
          if (mo["InstanceName"].ToString().StartsWith(_driverId))
          {
            Console.WriteLine("| {0} {1} - {2}", _os_found, mo["InstanceName"], mo["PortName"]);
            return (string)mo["PortName"];
          }
        }
      }
      catch (ManagementException me)
      {
        Console.WriteLine("| * WMI {0}: {1}", _os_error, me.Message);
      }

      return wiringPort;
    }

    ///
    /// Promts the user for a port name
    ///
    /// A valid COM port name
    private static string SetPortName()
    {
      Console.WriteLine("| {0} - {1}", _os_notfound, _driverId);
      Console.WriteLine("| {0}({1}):", _os_selectport, _serialPort.PortName);

      string portName = Console.ReadLine();

      if (!portName.StartsWith("COM"))
      {
        portName = _serialPort.PortName;
      }

      return portName;
    }

  }
}