开发者

Accessing COM10 or greater port in C#

I am using Visual Studio 2010 and programing in C# (.NET 3.5).

I want to write/read data from COM10.

Here is the simple code for that:

static void Main(string[] args)
{
    String Portname = String.Empty;

    /* List out all COM ports present on the computer. */
    foreach (string ports in SerialPort.GetPortNames())
    {
        Console.WriteLine(ports);
        /* If COM10 exists, copy the name for further use. */
        if (ports == "COM10")
        {
            Portname = ports; //I also tried this: "\\.\\COM10";
        }
    }
    /* If COM10 not found, return */
    if (Portname == String.Empty)
    {
        Console.WriteLine("Exiting");
        return;
    }

    SerialPort Port = new SerialPort(Portname,
                                     9600,          // Baudrate
                                     Parity.None,   //Parity
                                     8,             //DataBits
                                     StopBits.One); //Stop Bits

    Port.Open();

    for (int count = 0; count < 5; count++)
    {
        Port.WriteLine("\nHello");
    }
    Port.Close();

    while (true)开发者_如何转开发;
}

Whenever I use Portname as "COM10" in SerialPort Port = new SerialPort(Portname,9600,.....);, it gives an error as

The port 'COM10' does not exist

On Port.Open(), it should not even reach to command Port.Open() if COM10 doesn't exist.

Another way, I tried Portname as "\.\COM10". It gives an error as

The given port name does not start with COM/com or does not resolve to a valid serial port.

This happens with any port number greater than COM9.

Is there a way out?


The reason why you can't open a serial port greater than 10 is because FCL SerialPort implemented like in the following sample:

[MonitoringDescription("PortName")]
[Browsable(true)]
[DefaultValue("COM1")]
public string PortName
{
  [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
  {
    return this.portName;
  }
  set
  {
    if (value == null)
      throw new ArgumentNullException("PortName");
    if (value.Length == 0)
      throw new ArgumentException(SR.GetString("PortNameEmpty_String"), "PortName");
    if (value.StartsWith("\\\\", StringComparison.Ordinal))
      throw new ArgumentException(SR.GetString("Arg_SecurityException"), "PortName");
    if (this.IsOpen)
      throw new InvalidOperationException(SR.GetString("Cant_be_set_when_open", new object[1]
      {
        (object) "PortName"
      }));
    else
      this.portName = value;
  }
}

As you see, standard SerialPort does not allow you to use \\.\ notation in the port name. And I don't know why they did this. With \\.\ notation, ports greater than 10 can be opened. So, the only way is to implement your own SerialPort component.


I don't think GetPortNames() or Open() are causing your issue: my bet is that it's hardware-related. Have you tried your code on a different machine?

Unfortunately, i don't have direct experience with your scenario, since two-digit ports have always worked for me... But there's one thing i'd like to note: i've learned in time that it's better to be safe than sorry, and thus i've increased my usage of try-catch blocks. In your case, i'd do this:

    static System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
    private static int defaultBaudRate = 9600, defaultDataBits = 8;
    static System.IO.Ports.SerialPort TryOpeningPort(string portName)
    {
        System.IO.Ports.SerialPort port = null;
        timer.Start();
        try
        {
            port = new System.IO.Ports.SerialPort(portName,
                defaultBaudRate, System.IO.Ports.Parity.None, defaultDataBits, System.IO.Ports.StopBits.One);
            port.Open();
            port.Close();
            /**/Console.WriteLine(portName + " : OK");
        }
        catch (Exception exceptionInfo) //most common is System.UnauthorizedAccessException
        {
            port = null;
            /**/Console.WriteLine(portName + " -- " + exceptionInfo.GetType().ToString() + " : " + exceptionInfo.Message);
        }
        timer.Stop();
        //Console.WriteLine("Elapsed time : " + timer.ElapsedMilliseconds + "ms" + System.Environment.NewLine);
        timer.Reset();
        return port;
    }

You can call this either directly, as in:

        TryOpeningPort("COM10");

or using your initial-check approach:

        foreach (string portName in System.IO.Ports.SerialPort.GetPortNames())
            if (portName.Equals("Com10", StringComparison.InvariantCultureIgnoreCase))
                TryOpeningPort(portName);


  • For port smaller or equal to 9: new SerialPort("COM9")
  • For port greater than 9: new SerialPort("\\\\.\\COM10")

I tested the use of the property serialArduino.PortName = ... for ports greater than 9, but this was always leading to errors, so I used the constructor new SerialPort().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜