Try adding the System.IO.Ports NuGet package:
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
Also note that the fully qualified name is System.IO.Ports.SerialPort, not System.IO.SerialPort
C# .Net 6.0 System.IO.Ports is depricated. How can I use SerialPort? - Stack Overflow
c# - Why System.IO.Ports.SerialPort.GetPortNames() produces a DirectoryNotFoundException? - Stack Overflow
System.IO.Ports isn't finding every com port?
IL2CPP NotSupportedException SerialPort::GetPortNames - Unity Engine - Unity Discussions
There is no single built-in Windows command that lists "All Ports + Busy Status" in one view. We effectively have two approaches: the Non-Invasive method (inspecting OS handles) or the Native method (trying to open the port to see if it fails).
Method 1: The Non-Invasive Way
If we want to check port status without physically opening/closing them (which can reset devices), one must inspect the Windows Object Manager handles. This requires looking at who is holding the port, rather than asking the port if it is open.
Option A: Sysinternals Handle (Immediate)
This is the industry standard for inspecting port usage. It is not built-in, but can be installed via Winget/Scoop/Choco (winget install Microsoft.Sysinternals.Handle).
Run as Administrator:
handle -a "Device\Serial"
- Empty Result: The port is free.
- Result Found: It lists exactly which process (PID and Name) is hogging the port.
Option B: Native openfiles (Requires Reboot)
If one cannot install tools, you can use the native openfiles command, but it requires enabling the system-wide "Maintain Objects List" flag, which costs a small amount of RAM and requires a reboot.
- Enable (run once):
openfiles /local on - Reboot.
- Check ports:
openfiles /query /FO TABLE | findstr "Serial"
Method 2: The Native PowerShell Script (Invasive)
If you cannot use external tools or reboot, you must use the "Try/Catch" method. This script iterates through all known ports, attempts to open them, and infers their status based on whether the OS throws an "Access Denied" error.
Note: This is "invasive"—opening the port, even for a millisecond, may cause DTR/RTS lines to toggle, potentially resetting connected hardware (like Arduino/ESP32 boards).
# Get all physically/logically present serial ports
$ports = [System.IO.Ports.SerialPort]::GetPortNames()
$portStatuses = @()
foreach ($port in $ports) {
$status = 'Available'
try {
# Attempt to open and immediately close the port
$testPort = New-Object System.IO.Ports.SerialPort $port
$testPort.Open()
$testPort.Close()
}
catch {
# If Open() fails, the port is likely in use by another app (or PS itself)
$status = 'Busy'
}
$portStatuses += [PSCustomObject]@{
PortName = $port
Status = $status
}
}
# Display cleanly
$portStatuses | Format-Table -AutoSize
Why the original commands were confusing:
[System.IO.Ports.SerialPort]::getportnames()only queries the registry for existence, so it always lists the port even if it's busy.modeonly interacts with the driver configuration. If a port is actively locked by another process,modeoften fails or hides it, leading to the discrepancy I saw where PowerShell "hides" the port frommodeonce it opens a handle.
Try this :
- Click on a start menu
- Go to "run"
- in the field type CMD
- execute this commands in this order: a) C:>powershell b) PS> Get-WMIObject Win32_SerialPort
If you are x64 so type win64.
It should work i guess.
Hello.
It seems as though visual studio isn't able to find my CP210x device on COM2 while it can find everything else?
I'm at a loss as to why this is happening. is it because its UART?
my device manager:
my code: in a nutshell it finds available com ports and connects to it to send messages.
what my program finds: COM2 is not shown
com read code: on form start, copy coms to drop down list
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
comboBoxCOMPORT.Items.AddRange(ports);
}
I've seen the strange characters too. My solution is using Regular Expressions to filter out the number portion of the comm port name.
Dim ports As New Devices.Ports
For Each s As String In ports.SerialPortNames
s = Regex.Replace(s, "\D*(\d+)\D*", "$1")
Debug.WriteLine(s)
Next
I've had this exact same problem with USB CDC serial devices, handled by the new rewritten Windows 10 usbser.sys driver.
The garbage characters are often digits, so removing non-digits isn't a reliable way to work around it. For my solution, look at my last post on this thread here:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/a78b4668-ebb6-46aa-9985-ec41667abdde/ioportsserialportgetportnames-registrykeygetvalue-corruption-with-usbsersys-driver-on-windows?forum=netfxbcl
..there is code there that'll go through the registry, find usbser ports, and return their unmangled names. Beware that it doesn't return all serial ports, just ones provided by that driver. The code works on Windows XP through to 10.
The underlying problem is that the usbser.sys driver creates a registry entry, and on .NET (at least up to 3.5) the GetPortNames() function tries to read those registry keys and gets corrupted data. I've reported this to Microsoft, both via that forum (assuming they read it) and using the built-in Windows 10 beta error reporting tool. Maybe one day there will be a fix.