【问题标题】:What is proper way to detect all available serial ports on Windows?在 Windows 上检测所有可用串行端口的正确方法是什么?
【发布时间】:2010-04-20 09:49:08
【问题描述】:

有几种方法可以在 Windows 下列出串行端口,但我不确定什么是正确的方法:检测所有可用串行端口的方法。

一个很好的代码示例是http://www.naughter.com/enumser.html - 其中有 9 种(九种!)枚举串行设备的方法。

问题是:最佳的做法是什么。

要求:

  • 不要打开端口以检查它们是否可用。
  • 能够检测名称与COMx 不同的端口。
  • 在 Windows XP SP2 或更高版本上工作

【问题讨论】:

    标签: c++ c windows serial-port


    【解决方案1】:
    void SelectComPort() //added function to find the present serial 
    {
    
        TCHAR lpTargetPath[5000]; // buffer to store the path of the COMPORTS
        DWORD test;
        bool gotPort=0; // in case the port is not found
    
        for(int i=0; i<255; i++) // checking ports from COM0 to COM255
        {
            CString str;
            str.Format(_T("%d"),i);
            CString ComName=CString("COM") + CString(str); // converting to COM0, COM1, COM2
    
            test = QueryDosDevice(ComName, (LPSTR)lpTargetPath, 5000);
    
                // Test the return value and error if any
            if(test!=0) //QueryDosDevice returns zero if it didn't find an object
            {
                m_MyPort.AddString((CString)ComName); // add to the ComboBox
                gotPort=1; // found port
            }
    
            if(::GetLastError()==ERROR_INSUFFICIENT_BUFFER)
            {
                lpTargetPath[10000]; // in case the buffer got filled, increase size of the buffer.
                continue;
            }
    
        }
    
        if(!gotPort) // if not port
        m_MyPort.AddString((CString)"No Active Ports Found"); // to display error message incase no ports found
    
    }
    

    【讨论】:

    • 这一行没有做任何事情:lpTargetPath[10000];
    • 希望使用动态 lpTargetPath,然后在 INSUFFICIENT_BUFFER 分支中: lpTargetPath = realloc(lpTargetPath, bufSize);缓冲区大小*=2; i--;
    【解决方案2】:

    如果您可以访问注册表,HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM 键包含 Windows 当前支持的 COM 端口列表(在某些情况下,此信息可能是陈旧/不正确的;我怀疑,当即插即用设备提供串行ports 尚未完成检测/安装或最近被删除)。

    这是.NET Framework的SerialPort.GetPortNames()方法报告可用COM端口的方式,以上信息来源于链接页面。

    【讨论】:

    • 在 Windows 10 中看不到此注册表路径
    【解决方案3】:

    串行端口是非常简单的设备,可以追溯到计算硬件的石器时代。他们不支持即插即用,无法判断有人插入了设备。您唯一能做的就是发现可用的端口,SerialPort.GetPortNames() 返回列表。一些 USB 仿真器可以生成一个描述性的名称来配合端口名称,您可以发现那些带有 WMI、Win32_SerialPort 类的。

    这些都不能帮助您发现连接到特定设备的 COM 端口。只有人类知道,她将电缆插入连接器。您需要提供一个配置 UI,让用户选择端口号。一个组合框可以完成工作。将选择保存在您的配置数据中,非常下次您的程序启动时设备仍连接到同一个端口。

    【讨论】:

    • 我使用 SerialPort.GetPortNames()。
    • 串口被低估了!有时我不想要任何复杂的即插即用问题。我只想插入电缆并输入。 RS232 万岁!
    • @LightnessRacesinOrbit Com 端口很好,直到您必须尝试检测何时添加了一个,然后它们就是地狱。
    【解决方案4】:

    这是@michael-jacob-mathew 答案的现代化版本:

    #include <iostream>
    #include <string>
    #include <Windows.h>
    
    bool SelectComPort() //added function to find the present serial 
    {
        char lpTargetPath[5000]; // buffer to store the path of the COMPORTS
        bool gotPort = false; // in case the port is not found
    
        for (int i = 0; i < 255; i++) // checking ports from COM0 to COM255
        {
            std::string str = "COM" + std::to_string(i); // converting to COM0, COM1, COM2
            DWORD test = QueryDosDevice(str.c_str(), lpTargetPath, 5000);
    
            // Test the return value and error if any
            if (test != 0) //QueryDosDevice returns zero if it didn't find an object
            {
                std::cout << str << ": " << lpTargetPath << std::endl;
                gotPort = true;
            }
    
            if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
            }
        }
    
        return gotPort;
    }
    

    它在我的电脑上产生以下输出:

    COM1: \Device\Serial0
    COM3: \Device\VCP0
    

    【讨论】:

      【解决方案5】:

      修改 @Dženan 答案以使用宽字符并返回整数列表

      #include <string>
      #include <list>
      
      list<int> getAvailablePorts()
      {
          wchar_t lpTargetPath[5000]; // buffer to store the path of the COM PORTS
          list<int> portList;
      
          for (int i = 0; i < 255; i++) // checking ports from COM0 to COM255
          {
              wstring str = L"COM" + to_wstring(i); // converting to COM0, COM1, COM2
              DWORD res = QueryDosDevice(str.c_str(), lpTargetPath, 5000);
      
              // Test the return value and error if any
              if (res != 0) //QueryDosDevice returns zero if it didn't find an object
              {
                  portList.push_back(i);
                  //std::cout << str << ": " << lpTargetPath << std::endl;
              }
              if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
              {
              }
          }
          return portList;
      }
      

      【讨论】:

        【解决方案6】:

        您可以检查 Windows 注册表库以列出所有 COM 端口。这是我的代码>github file

        【讨论】:

          【解决方案7】:
          CUIntArray ports;
          EnumerateSerialPorts(ports);
          
          for (int i = 0; i<ports.GetSize(); i++)
          {
              CString str;
              str.Format(_T("COM%d"), ports.ElementAt(i));
              m_ctlPort.AddString(str);
          }
          

          【讨论】:

          • 或者确切地说是引用了哪个库
          猜你喜欢
          • 2011-06-19
          • 1970-01-01
          • 2015-08-08
          • 1970-01-01
          • 2010-10-13
          • 1970-01-01
          • 2016-08-09
          • 1970-01-01
          • 2014-09-01
          相关资源
          最近更新 更多