C#检查COM(串行)端口是否已打开

时间:2008-10-12 13:24:38

标签: c# .net serial-port

是否有一种简单的方法可以通过编程方式检查串口COM端口是否已经打开/正在使用?

通常我会使用:

try
{
    // open port
}
catch (Exception ex)
{
    // handle the exception
}

但是,我想以编程方式检查,以便我可以尝试使用另一个COM端口或其他一些。

9 个答案:

答案 0 :(得分:14)

我不久前需要类似的东西来搜索设备。

我获得了一个可用的COM端口列表,然后简单地迭代它们,如果它没有抛出异常,我试图与设备通信。有点粗糙但有效。

var portNames = SerialPort.GetPortNames();

foreach(var port in portNames) {
    //Try for every portName and break on the first working
}

答案 1 :(得分:12)

我就这样做了:

      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, IntPtr securityAttrs, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

然后在

        int dwFlagsAndAttributes = 0x40000000;

        var portName = "COM5";

        var isValid = SerialPort.GetPortNames().Any(x => string.Compare(x, portName, true) == 0);
        if (!isValid)
            throw new System.IO.IOException(string.Format("{0} port was not found", portName));

        //Borrowed from Microsoft's Serial Port Open Method :)
        SafeFileHandle hFile = CreateFile(@"\\.\" + portName, -1073741824, 0, IntPtr.Zero, 3, dwFlagsAndAttributes, IntPtr.Zero);
        if (hFile.IsInvalid)
            throw new System.IO.IOException(string.Format("{0} port is already open", portName));

        hFile.Close();


        using (var serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One))
        {
            serialPort.Open();
        }

答案 2 :(得分:1)

SerialPort class有一个Open方法,会抛出一些例外。 上面的参考包含详细的例子。

另请参阅IsOpen属性。

一个简单的测试:

using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.Text;

namespace SerPort1
{
class Program
{
    static private SerialPort MyPort;
    static void Main(string[] args)
    {
        MyPort = new SerialPort("COM1");
        OpenMyPort();
        Console.WriteLine("BaudRate {0}", MyPort.BaudRate);
        OpenMyPort();
        MyPort.Close();
        Console.ReadLine();
    }

    private static void OpenMyPort()
    {
        try
        {
            MyPort.Open();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error opening my port: {0}", ex.Message);
        }
    }
  }
}

答案 3 :(得分:1)

我想打开下一个可用的端口并这样做。 请注意,它不是用于 WPF,而是用于 Windows 窗体。 我用可用的 com 端口填充了一个组合框。 然后我尝试打开第一个。如果失败,我会从组合框中选择下一个可用项目。如果选定的索引最终没有改变,则没有可用的备用通信端口,我们会显示一条消息。

private void GetPortNames()
{
    comboBoxComPort.Items.Clear();
    foreach (string s in SerialPort.GetPortNames())
    {
        comboBoxComPort.Items.Add(s);
    }
    comboBoxComPort.SelectedIndex = 0;
}

private void OpenSerialPort()
{
    try
    {
        serialPort1.PortName = comboBoxComPort.SelectedItem.ToString();
        serialPort1.Open();
    }
    catch (Exception ex)
    {
        int SelectedIndex = comboBoxComPort.SelectedIndex;
        if (comboBoxComPort.SelectedIndex >= comboBoxComPort.Items.Count - 1)
        {
            comboBoxComPort.SelectedIndex = 0;
        }
        else
        {
            comboBoxComPort.SelectedIndex++;
        }
        if (comboBoxComPort.SelectedIndex == SelectedIndex)
        {
            buttonOpenClose.Text = "Open Port";
            MessageBox.Show("Error accessing port." + Environment.NewLine + ex.Message, "Port Error!!!", MessageBoxButtons.OK);
        }
        else
        {
            OpenSerialPort();
        }
    }

    if (serialPort1.IsOpen)
    {
        StartAsyncSerialReading();
    }
}

答案 4 :(得分:0)

这对我有用。

private string portName { get; set; } = string.Empty;

    /// <summary>
    /// Returns SerialPort Port State (Open / Closed)
    /// </summary>
    /// <returns></returns>
    internal bool HasOpenPort()
    {
        bool portState = false;

        if (portName != string.Empty)
        {
            using (SerialPort serialPort = new SerialPort(portName))
            {
                foreach (var itm in SerialPort.GetPortNames())
                {
                    if (itm.Contains(serialPort.PortName))
                    {
                        if (serialPort.IsOpen) { portState = true; }
                        else { portState = false; }
                    }
                }
            }
        }

        else { System.Windows.Forms.MessageBox.Show("Error: No Port Specified."); }

        return portState;
    }

如果您需要捕获SerialPort(开放)异常: https://docs.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.open?view=netframework-4.7.2

答案 5 :(得分:0)

分享对我有用的东西(一种简单的帮助方法):

private string portName { get; set; } = string.Empty;

    /// <summary>
    /// Returns SerialPort Port State (Open / Closed)
    /// </summary>
    /// <returns></returns>
    internal bool HasOpenPort()
    {
        bool portState = false;

        if (portName != string.Empty)
        {
            using (SerialPort serialPort = new SerialPort(portName))
            {
                foreach (var itm in SerialPort.GetPortNames())
                {
                    if (itm.Contains(serialPort.PortName))
                    {
                        if (serialPort.IsOpen) { portState = true; }
                        else { portState = false; }
                    }
                }
            }
        }

        else { System.Windows.Forms.MessageBox.Show("Error: No Port Specified."); }

        return portState;
}


注释:
-对于更高级的技术,我建议使用ManagementObjectSearcher Class
更多信息Here
-对于Arduino设备,我将端口保持打开状态。
-如果需要捕获异常,建议使用Try Catch块。
-另请检查:“ TimeoutException”
-有关如何获取SerialPort(开放)异常Here的更多信息。

答案 6 :(得分:0)

  public void MobileMessages(string ComNo, string MobileMessage, string MobileNo)
    {
        if (SerialPort.IsOpen )
            SerialPort.Close();
        try
        {
            SerialPort.PortName = ComNo;
            SerialPort.BaudRate = 9600;
            SerialPort.Parity = Parity.None;
            SerialPort.StopBits = StopBits.One;
            SerialPort.DataBits = 8;
            SerialPort.Handshake = Handshake.RequestToSend;
            SerialPort.DtrEnable = true;
            SerialPort.RtsEnable = true;
            SerialPort.NewLine = Constants.vbCrLf;
            string message;
            message = MobileMessage;

            SerialPort.Open();
            if (SerialPort.IsOpen  )
            {
                SerialPort.Write("AT" + Constants.vbCrLf);
                SerialPort.Write("AT+CMGF=1" + Constants.vbCrLf);
                SerialPort.Write("AT+CMGS=" + Strings.Chr(34) + MobileNo + Strings.Chr(34) + Constants.vbCrLf);
                SerialPort.Write(message + Strings.Chr(26));
            }
            else
                ("Port not available");
            SerialPort.Close();
            System.Threading.Thread.Sleep(5000);
        }
        catch (Exception ex)
        {

                message.show("The port " + ComNo + " does not exist, change port no ");
        }
    }

答案 7 :(得分:0)

对于无法使用SerialPort.GetPortNames();的人,因为他们没有针对.net framework(例如,在我的情况下,我使用的是.Net Core而不是.Net Framework),这就是我的最终目的:

在命令提示符下,如果您键入mode,您将得到以下内容:

enter image description here

mode是位于C:\Windows\System32\mode.com的可执行文件。只需使用如下正则表达式解析该可执行文件的结果:

// Code that answers the question

var proc = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = @"C:\Windows\System32\mode.com",
        UseShellExecute = false,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    }
};

proc.Start();
proc.WaitForExit(4000); // wait up to 4 seconds. It usually takes less than a second

// get ports being used
var output = proc.StandardOutput.ReadToEnd();

现在,如果您想解析输出,这就是我的方法:

List<string> comPortsBeingUsed = new List<string>();
Regex.Replace(output, @"(?xi) status [\s\w]+? (COM\d) \b ", regexCapture =>
{
    comPortsBeingUsed.Add(regexCapture.Groups[1].Value);
    return null;
});

foreach(var item in comPortsBeingUsed)
{
    Console.WriteLine($"COM port {item} is in use");
}

答案 8 :(得分:-2)

您可以尝试使用以下代码来检查端口是否已打开。我猜你不知道要检查哪个端口。

foreach (var portName in Serial.GetPortNames()
{
  SerialPort port = new SerialPort(portName);
  if (port.IsOpen){
    /** do something **/
  }
  else {
    /** do something **/
  }
}