How to locate a specific Serial Port? - c#

The following code returns only three serial ports (com3, com4 and com5). The firmware that I would like to access is located on a USB plug multiplier. How can I access the serial ports of this mulitplier and how can I identify the specific USB containing the firmware that I want to send information to?
using System;
using System.IO.Ports;
namespace SerialPortExample
{
class SerialPortExample
{
public static void Main()
{
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
foreach (string port in ports)
{
Console.WriteLine(port);
}
Console.ReadLine();
}
}
}
Many thanks in advance!

This is a pretty big usability problem and caused by USB drivers taking a shortcut and emulating a serial port to make it easy to interface with them. Serial ports are very primitive devices, which makes their api very easy to use. But lacks any kind of support for plug-and-play, there's no way to get a decent notification for them. The driver just picks an arbitrary port number and it is up to the user to figure out which one it might be. Trial and error stuff. This didn't use to be a problem, serial ports had a connector mounted on the machine's back panel that was clearly labeled with the COM port name.
You can possibly get some mileage out of WMI, it lets you enumerate serial port devices with the Win32_SerialPort query. What you get is fairly unpredictable, it completely depends on the driver to supply the data. Best way to experiment with that is with the WMI Code Creator utility, it can also auto-generate the C# code you need. Unfortunately I can't find the download location anymore, this appears to have been removed in the past couple of weeks. Hope you can find an alternative.

The code below does a good job finding the specific ports:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Windows.Forms;
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass x = new MyClass();
var com = x.GetCOMs();
foreach (string port in com)
{
Console.WriteLine(port);
}
Console.ReadLine();
}
}
class MyClass
{
public List<string> GetCOMs()
{
List<string> coms = new List<string>();
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0");
foreach (ManagementObject obj in searcher.Get())
{
object captionObj = obj["Caption"];
if (captionObj != null)
{
string caption = captionObj.ToString();
if (caption.Contains("(COM"))
{
coms.Add(caption);
}
}
}
m_ParseCOMs(ref coms);
}
catch (ManagementException ex)
{
MessageBox.Show("An error occurred while querying for WMI data: " + ex.Message);
return coms;
}
return coms;
}
private void m_ParseCOMs(ref List<string> comPorts)
{
string[] temp;
List<string> temp2 = new List<string>();
int index = 0;
foreach (string s in comPorts)
{
string temp3 = "";
temp = s.Split(' ');
temp3 += temp[temp.Length - 1] + " - ";
for (int i = 0; i < temp.Length - 1; i++)
{
temp3 += temp[i] + " ";
}
temp2.Insert(index, temp3);
index++;
}
comPorts = temp2;
}
}
}

Related

NetworkInterface.GetAllNetworkInterfaces Method () doesn't match all the results from "ipconfig /all"

So the problem is that the method returns different results from the ones you get from using the command "ipconfig /all" in cmd. Some adapters are returned the right way, but some are not, and information is missing or its different. For example, some of the description lines in ipconfig match the ones in my wpf program, but some don't or are empty. All i pretty much want it to do is return a proper DNS suffix, description/name and the physical address itself.
Main Window
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void detectButton_Click(object sender, RoutedEventArgs e)
{
List<MacAddress> macAddresses = GetMacAddresses();
for (int i = 1; i < macAddresses.Count; i++)
{
Label label = (Label)this.FindName("label" + i.ToString());
label.Content = "Connection Specific DNS suffix: " + macAddresses[i].connectionSpecificDnsSuffix + Environment.NewLine
+ "Description: " + macAddresses[i].description + Environment.NewLine +
"Physical Address: " + macAddresses[i].physicalAddress;
}
int count = 0;
foreach (var item in macAddresses)
{
count += 1;
}
}
internal List<MacAddress> GetMacAddresses()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
List<MacAddress> macAdresses = new List<MacAddress>();
foreach (NetworkInterface adapter in nics)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
MacAddress address = new MacAddress();
address.connectionSpecificDnsSuffix = properties.DnsSuffix;
address.description = adapter.Name;
address.physicalAddress = adapter.GetPhysicalAddress().ToString();
macAdresses.Add(address);
}
return macAdresses;
}
Class for storing data
class MacAddress
{
public string connectionSpecificDnsSuffix;
public string description;
public string physicalAddress;
}
Edit:
cmd results
Picture 1
Returned results
Picture 2
You're probably not catching the right address. I'd suggest looping throught each MacAddress with a foreach loop and adding them to UI dynamically.
Infact, I tried and it works. Your method of looping is just wrong.

ManagmentObject queries for windows (C#) to find usb device

I'm trying to find a particular USB device (1 or more) connected to my computer and retrieve the relevant path to the mounted drive. Ideally, it would be by finding the VID/PID of the USB device, but I'm not sure how to do that yet. The following works, but there must be some way to get the data in a single query.
What I'm doing here is looking or a physical drive that has a model matching HS SD Card Bridge USB Device and finding the physical drive # associated and using that to find the mounted partition..
foreach (ManagementObject disk in disks.Get()) {
//look for drives that match our string
Match m = Regex.Match(disk["model"].ToString(), "HS SD Card Bridge USB Device");
if (m.Success) {
m = Regex.Match(disk["DeviceID"].ToString(), #"PHYSICALDRIVE(\d+)");
if (m.Success) {
int driveNumber = Int32.Parse(m.Groups[1].ToString());
ManagementObjectSearcher mapping = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDiskToPartition");
foreach (ManagementObject map in mapping.Get()) {
m = Regex.Match(map["Antecedent"].ToString(), #"Disk #" + driveNumber + ",");
if (m.Success) {
string drive = map["Dependent"].ToString();
m = Regex.Match(drive, #"([A-Z]):");
if (m.Success) {
drive = m.Groups[1].ToString(); //< -- **FOUND**
}
}
}
//USBDevice dev = new USBDevice("", "");
// list.Items.Add();
Console.WriteLine("");
}
}
}
is there a way to do this from the VID/PID and a way to construct the search query so it requires just one query?
This is the one I used earlier . This will not be the answer. But will help you .
public int GetAvailableDisks()
{
int deviceFound = 0;
try
{
// browse all USB WMI physical disks
foreach (ManagementObject drive in
new ManagementObjectSearcher(
"select DeviceID, Model from Win32_DiskDrive where InterfaceType='USB'").Get())
{
ManagementObject partition = new ManagementObjectSearcher(String.Format(
"associators of {{Win32_DiskDrive.DeviceID='{0}'}} where AssocClass = Win32_DiskDriveToDiskPartition",
drive["DeviceID"])).First();
if (partition == null) continue;
// associate partitions with logical disks (drive letter volumes)
ManagementObject logical = new ManagementObjectSearcher(String.Format(
"associators of {{Win32_DiskPartition.DeviceID='{0}'}} where AssocClass = Win32_LogicalDiskToPartition",
partition["DeviceID"])).First();
if (logical != null)
{
// finally find the logical disk entry to determine the volume name - Not necesssary
//ManagementObject volume = new ManagementObjectSearcher(String.Format(
// "select FreeSpace, Size, VolumeName from Win32_LogicalDisk where Name='{0}'",
// logical["Name"])).First();
string temp = logical["Name"].ToString() + "\\";
// +" " + volume["VolumeName"].ToString(); Future purpose if Device Name required
deviceFound++;
if (deviceFound > 1)
{
MessageBox.Show(#"Multiple Removeable media found. Please remove the another device");
deviceFound--;
}
else
{
driveName = temp;
}
}
}
}
catch (Exception diskEnumerateException)
{
}
return deviceFound;
}

C# DNS.GetHostEntry() .. new programmer new to network programming

I am really unfamiliar with C#, it's been years since I've programmed with this language. I'm going to post the code I have, which has build errors. This is what I'm trying to do, but I really am not sure how to proceed. I have hit a wall and really have no clue how to proceed:
Enter an address (as a string)
Resolve the address using the appropriate function
Print out the complete host information
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace CSDNS
{
class Program
{
static void PrintHostInfo(String host)
{
{
IPHostEntry hostinfo;
try
{
hostinfo = Dns.GetHostEntry("www.sunybroome.edu"); // DNS Name Resolution
//
// The IP address is now in hostinfo structure
// Print out the contents of hostinfo structure
// in an easily readable form with labels. For
// example, the host name can be output using:
Console.WriteLine("Hostname = {0}\n", hostinfo.HostName);
}
catch
{
// Print out the exception here...
}
try
{
IPHostEntry hostInfo;
//Attempt to resolve DNS for given host or address
hostInfo = Dns.Resolve(host);
//Display the primary host name
Console.WriteLine("\tCanonical Name: " + hostInfo.HostName);
//Display list of IP addresses for this host
Console.Write("\tIP Addresses: ");
foreach (IPAddress ipaddr in hostInfo.AddressList)
{
Console.Write(ipaddr.ToString() + " ");
}
Console.WriteLine();
//Display list of alias names for this host
Console.Write("\tAliases: ");
foreach (String alias in hostInfo.Aliases)
{
Console.Write(alias + " ");
}
Console.WriteLine("\n");
}
catch (Exception)
{
Console.WriteLine("\tUnable to resolve host: " + host + "\n");
}
}
}
static void Main(string[] args)
{
//Get and print local host info
try
{
Console.WriteLine("Local Host:");
String localHostName = Dns.GetHostName();
Console.WriteLine("\tHost Name: " + localHostName);
PrintHostInfo(localHostName);
}
catch (Exception)
{
Console.WriteLine("Unable to resolve local host\n");
}
//Get and print info for hosts given on command line
foreach (String arg in args)
{
Console.WriteLine(arg + ":");
PrintHostInfo(arg);
}
}
}
}
You need to pass in host to the Resolve method, not hostInfo (i.e. the string that contains the host you want to resolve):
hostInfo = Dns.Resolve(host);

GET FRIENDLY PORT NAME Programmatically

Anyone here has an idea where I can get the ports name listed in my PC?
By using this code:
For i As Integer = 0 To My.Computer.Ports.SerialPortNames.Count - 1
cmbPort.Properties.Items.Add(My.Computer.Ports.SerialPortNames(i))
Next
I could get COM26 and etc. if any, but that's not what I want. Instead of retrieving COM26, I want USB-SERIAL CH340 or USB-SERIAL CH340 (COM26). How could I do that?
I got mixed results from other answers.
I've come up with this code working better for me.
Add Reference to System.Management in your application
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE Caption like '%(COM%'"))
{
var portnames = SerialPort.GetPortNames();
var ports = searcher.Get().Cast<ManagementBaseObject>().ToList().Select(p => p["Caption"].ToString());
var portList = portnames.Select(n => n + " - " + ports.FirstOrDefault(s => s.Contains(n))).ToList();
foreach (var i in portList)
{
Console.WriteLine(i);
}
}
Try this .
Public Shared Function ListFriendlyCOMPOrt() As List(Of String)
Dim oList As New List(Of String)
Try
Using searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_PnPEntity WHERE Caption like '%(COM26%'")
For Each queryObj As ManagementObject In searcher.Get()
oList.Add(CStr(queryObj("Caption")))
Next
End Using
Return oList
Catch err As ManagementException
MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
End Try
Return oList
End Function
That should work..
You could use WMI...
Add Reference to System.Management in your application
then,
shown on StackOverflow: Getting Serial Port Information
using System.Management;
using System.IO;
string result = "";
using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"))
{
string[] portnames = SerialPort.GetPortNames();
var ports = searcher.Get().Cast<ManagementBaseObject>().ToList();
var tList = (from n in portnames join p in ports on n equals p["DeviceID"].ToString() select n + " - " + p["Caption"]).ToList();
foreach (string s in tList)
{
result = result + s;
}
}
MessageBox.Show(result);
That isn't the name of the serial port; it is COM26. The name listed in the device manager is probably the name of the device providing the emulation.
Why do you want that name? If you describe your problem more completely, figuring out the solution will be easier.

power point printing problem using C#

I'm using the COM objects from Office 2007 to handle and print ms-office files. I don't have any problems with word and excel documents, but i just can't print Power Point docs.
the code bellow just opens the file send a job to the printer but nothing gets printed
what am i doing wrong? =(
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Main
{
class PrintPPoint
{
public static void PrintPPointDocument(string filename, int copies, string range)
{
Microsoft.Office.Interop.PowerPoint.Presentation work = null;
Microsoft.Office.Interop.PowerPoint.Application app = new Microsoft.Office.Interop.PowerPoint.ApplicationClass();
Microsoft.Office.Interop.PowerPoint.Presentations presprint = app.Presentations;
//app.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
work = presprint.Open(filename, Microsoft.Office.Core.MsoTriState.msoCTrue, Microsoft.Office.Core.MsoTriState.msoCTrue, Microsoft.Office.Core.MsoTriState.msoFalse);
work.PrintOptions.PrintInBackground = 0;
work.PrintOptions.ActivePrinter = app.ActivePrinter;
if (range.Equals("0"))
{
work.PrintOut(0, 1, app.ActivePrinter, copies, Microsoft.Office.Core.MsoTriState.msoFalse);
}
else
{
string[] toprintsheet = range.Split(new char[] { ',' });
foreach (string aux in toprintsheet)
{
work.PrintOptions.PrintInBackground = 0;
work.PrintOptions.ActivePrinter = app.ActivePrinter;
if (aux.Contains("-"))
{
int from = 0, to = 0;
string[] SplitRange = aux.Split(new char[] { '-' });
from = Convert.ToInt16(SplitRange[0]);
to = Convert.ToInt16(SplitRange[1]);
work.PrintOut(from, to, app.ActivePrinter, 1, Microsoft.Office.Core.MsoTriState.msoFalse);
}
else
{
work.PrintOut(Convert.ToInt16(aux), Convert.ToInt16(aux), app.ActivePrinter, copies, Microsoft.Office.Core.MsoTriState.msoFalse);
}
}
}
work.Close();
app.Quit();
}
}
}
I just needed to set
PrintOptions.PrintInBackground = Microsoft.Office.Core.MsoTriState.msoFalse
That lets the jobs complete.
I can't tell you but I bet you can easily find out yourself...
I assume that this is an application that interacts with the desktop and not some background service.
I would step through the code slowly and see if it works.. (for both app.visible = true and not.) If it works, it may be a race between ppoint printing functionality and ppoint closing the document/quiting. (Even though you've turned off background printing) and you have check for that...
Good luck

Categories