2025 Master COM Ports with C++ | Full VSCode Development Guide
In the field of Internet of Things (IoT), the COM port (serial port) remains a crucial method for data transmission between many devices. While modern hardware often relies on more advanced interfaces like USB, COM ports still play a vital role in embedded systems, industrial automation, and legacy hardware.
In this article, we’ll demonstrate how to develop a cross-platform COM port listing tool using C++, and explore how this can be extended for IoT applications—helping you manage and monitor your devices more efficiently.

Contents
Why Choose C++ for Development?
High Performance:
C++ is a compiled language that generates highly efficient machine code, making it suitable for applications requiring high performance and real-time response. Compared to interpreted languages like Python, C++ is much faster—especially when dealing with large datasets, game development, or embedded systems where performance is critical.
Resource Control:
C++ allows developers precise control over memory, which is crucial for low-level system tuning or hardware interaction (such as drivers or embedded systems). In contrast, languages like Java and C# rely on garbage collection and offer less control over memory management.
What is a COM Port?
A COM Port (short for Communication Port) is a hardware interface used for serial communication between a computer and external devices. It is commonly used for data transmission and was one of the most prevalent serial interfaces in older computers. COM ports are also referred to as serial ports or RS-232 ports.
Even though USB has largely replaced COM ports as the standard connection interface, COM ports are still widely used in certain domains—particularly in embedded systems, industrial equipment, legacy hardware, and some debugging applications.
Development Environment
Before getting started, make sure the following tools are installed:
- VSCode (Download)
- C++ Compiler (GCC / Clang / MSVC)
- CMake Tools Extension for VSCode
Create a C++ Project in VSCode
Inside the folder, create the following file structure:
Create a folder named serial_port_lister
and open it in VSCode.
serial_port_lister/
├── CMakeLists.txt # CMake build configuration
└── main.cpp # Code
COM Port Listing Code
Below is the C++ code that lists COM ports across different operating systems:
#include <iostream>
#include <vector>
#include <string>
#ifdef _WIN32
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
#pragma comment(lib, "setupapi.lib")
#elif defined(__APPLE__)
#include <dirent.h>
#include <sys/stat.h>
#else // Linux
#include <dirent.h>
#include <sys/stat.h>
#endif
std::vector<std::string> listSerialPorts() {
std::vector<std::string> ports;
#ifdef _WIN32
// Windows implementation
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE) {
return ports;
}
SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &deviceInfoData); i++) {
char buffer[256];
DWORD bufferSize = sizeof(buffer);
if (SetupDiGetDeviceRegistryPropertyA(
hDevInfo, &deviceInfoData, SPDRP_FRIENDLYNAME,
NULL, (PBYTE)buffer, bufferSize, &bufferSize)) {
ports.push_back(buffer);
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
#elif defined(__APPLE__)
// macOS implementation
DIR* dir = opendir("/dev");
if (dir) {
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
std::string name = entry->d_name;
if (name.find("cu.") == 0 || name.find("tty.") == 0) {
ports.push_back("/dev/" + name);
}
}
closedir(dir);
}
#else
// Linux implementation
DIR* dir = opendir("/dev");
if (dir) {
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
std::string name = entry->d_name;
if (name.find("ttyS") == 0 || name.find("ttyUSB") == 0 ||
name.find("ttyACM") == 0 || name.find("ttyAMA") == 0) {
ports.push_back("/dev/" + name);
}
}
closedir(dir);
}
#endif
return ports;
}
int main() {
std::cout << "Available COM Ports:" << std::endl;
auto ports = listSerialPorts();
if (ports.empty()) {
std::cout << "No COM ports found." << std::endl;
} else {
for (const auto& port : ports) {
std::cout << " - " << port << std::endl;
}
}
return 0;
}
Configure CMakeLists.txt
To build the project using CMake, you need to provide a CMakeLists.txt
file that describes how the project should be compiled and linked.
cmake_minimum_required(VERSION 3.10)
project(SerialPortLister VERSION 1.0.0)
# Basic settings
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Platform-specific settings
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
find_library(SETUPAPI_LIB setupapi)
message(STATUS "Found Windows setupapi.lib")
elseif(APPLE)
message(STATUS "Configuring for macOS")
else()
message(STATUS "Configuring for Linux")
endif()
# Main program
add_executable(${PROJECT_NAME}
main.cpp
)
# Link libraries
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE ${SETUPAPI_LIB})
endif()
# Installation settings (optional)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
# Packaging settings (optional)
include(InstallRequiredSystemLibraries)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
Build and Run
In VSCode, press Ctrl
(or Cmd
) + Shift
+ P
, then type and select “CMake: Build” to compile the project.
Once built, run the program (example for macOS):
./SerialPortLister
Output Example:
Available COM Ports:
- /dev/cu.usbserial-1234
- /dev/tty.usbserial-5678
Conclusion
This simple cross-platform application demonstrates how to list serial communication ports on different operating systems. By using conditional compilation, we can provide platform-specific implementations while maintaining a unified interface. You can further extend this program by adding features such as: Real-time port monitoring, A graphical user interface (GUI), Detailed port info (manufacturer, device ID, etc.).