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.
Related
This form of ManagementObject (using ".DeviceID=") assignment works:
// get number of logical drives on given physical disk
int n = 0;
var id = "\\\\.\\PHYSICALDRIVE0";
var disk = new ManagementObject("Win32_DiskDrive.DeviceID=" + "'" + id + "'");
foreach (ManagementObject dp in disk.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject ld in dp.GetRelated("Win32_LogicalDisk")) ++n;
}
This form of ManagementObject (using ".Number=") assignment fails:
// get number of logical drives on given physical disk
int n = 0;
var id = "0";
ManagementObject disk = new ManagementObject("root\\Microsoft\\Windows\\Storage:MSFT_Disk.Number=" + "'" + id + "'");
foreach (ManagementObject dp in disk.GetRelated("MSFT_Partition"))
{
foreach (ManagementObject ld in dp.GetRelated("MSFT_Volume")) ++n;
}
The exception is "Invalid object path". I have spent an embarrassing amount of time trying to figure out what I am doing wrong...and have no clue.
The specific item being searched for here is not the relevant issue. The proper syntax of using the two statements is what I am trying to understand...
The path for the working case is: "root\CIMV2" and the path to the failing case is: "root\Microsoft\Windows\Storage".
The failing statement is: "foreach (ManagementObject dp in disk.GetRelated("MSFT_Partition"))"
#user9938: I appreciate your reply and the focus on the MSFT_xxx items. I was looking for an analogous syntax solution to the Win32_xxx approach.
After considerable trial and error, it appears that the approach of assigning the specific disk directly in the ManagementObject declaration statement is simply not supported when using MSFT_Disk.
Either of these two statements work correctly:
var disk = new ManagementObject("Win32_DiskDrive=
var disk = new ManagementObject("Win32_DiskDrive.DeviceID=
There does not appear to be any analogous statement when using MSFT_Disk.
Thus, the simplest code solution is:
var phy = "0"; // ... or any valid disk index
int num = 0;
var disk = new ManagementObject("Win32_DiskDrive='\\\\.\\PHYSICALDRIVE" + phy + "'");
foreach (ManagementObject dp in disk.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject ld in dp.GetRelated("Win32_LogicalDisk")) ++num;
}
There are a number of ways to retrieve the information. Try the following instead:
private int GetNumberOfLogicalDrives(int number)
{
int numLogicalDrives = 0;
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(new ManagementScope(#"root\Microsoft\Windows\Storage"), new SelectQuery($"SELECT * FROM MSFT_Disk WHERE Number = {number}")))
{
using (ManagementObjectCollection logicalDrives = searcher.Get())
{
if (logicalDrives != null && logicalDrives.Count > 0)
{
foreach (ManagementObject mObj in logicalDrives)
{
//re-initialize
numLogicalDrives = 0;
if (mObj == null)
continue;
foreach (ManagementObject mObjDP in mObj.GetRelated("MSFT_Partition"))
{
if (mObjDP == null)
continue;
foreach (ManagementObject mObjLD in mObjDP.GetRelated("MSFT_Volume"))
{
if (mObjLD == null)
continue;
//skip if there isn't a drive letter
if (String.IsNullOrEmpty(mObjLD["DriveLetter"]?.ToString().Trim()))
continue;
numLogicalDrives++; //increment
}
}
Debug.WriteLine($"number: {number}; numLogicalDrives: {numLogicalDrives}");
}
}
}
}
return numLogicalDrives;
}
Usage:
int numLogicalDrives = GetNumberOfLogicalDrives(0);
Resources:
System.Management
how can i get a list of hard disks and their partitions(their logical drives) on my computer in c#?
iam looking for code that gives me similar results
harddisk0:partitions are C,D
harddisk1:partitions are C,F,D
i have tried this code
foreach (ManagementObject drive in search.Get())
{
string antecedent = drive["DeviceID"].ToString();
// the disk we're trying to find out about
antecedent = antecedent.Replace(#"\", "\\");
// this is just to escape the slashes
string query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='"
+ antecedent
+ "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
using (ManagementObjectSearcher partitionSearch = new ManagementObjectSearcher(query))
{
foreach (ManagementObject part in partitionSearch.Get())
{
//...pull out the partition information
Console.WriteLine("Dependent : {0}", part["Dependent"]);
}
}
}
knowing that dependent is a Reference to the instance representing the disk partition residing on the disk drive.
but iam getting the exception Not Found
what should i write please?
here is c# solution generated by me
foreach (ManagementObject drive in search.Get())
{
string antecedent = drive["DeviceID"].ToString(); // the disk we're trying to find out about
antecedent = antecedent.Replace(#"\", "\\"); // this is just to escape the slashes
string query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + antecedent + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
using (ManagementObjectSearcher partitionSearch = new ManagementObjectSearcher(query))
{
foreach (ManagementObject part in partitionSearch.Get())
{
//...pull out the partition information
MessageBox.Show(part["DeviceID"].ToString());
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + part["DeviceID"] + "'} WHERE AssocClass = Win32_LogicalDiskToPartition";
using (ManagementObjectSearcher logicalpartitionsearch = new ManagementObjectSearcher(query))
foreach (ManagementObject logicalpartition in logicalpartitionsearch.Get())
MessageBox.Show(logicalpartition["DeviceID"].ToString());
}
}
}
the plan of this code is described in this script https://blogs.technet.microsoft.com/heyscriptingguy/2005/05/23/how-can-i-correlate-logical-drives-and-physical-disks/
I have an old vb application which retrieves the disk id using this code.
Dim FSO As New Scripting.FileSystemObject
Dim Dr As Scripting.Drive
Dim id_convertido As Long = 0
Dim sRutaAplicacion As String = Application.StartupPath
Dim Valor As Integer = sRutaAplicacion.IndexOf(":\")
If Valor <> -1 Then
Dim RaizAplicacion As String
RaizAplicacion = Mid(sRutaAplicacion, 1, Valor)
For Each Dr In FSO.Drives
If Dr.DriveLetter = RaizAplicacion Then
Dim idDisco As String
idDisco = Dr.SerialNumber
id_convertido = (Microsoft.VisualBasic.Right(idDisco, 8))
Return id_convertido
End If
Next
End If
I'm want to achieve the same functionality in c#, so I found this code:
string HDD = System.Environment.CurrentDirectory.Substring(0, 1);
ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"" + HDD + ":\"");
disk.Get();
return disk["VolumeSerialNumber"].ToString();
but i get different values. In my first code, "idDisco" is "876823094", but in c#, this value is "34434236".
Both are checking disk c:
Any clues?
Thank you very much!
In my first code, "idDisco" is "876823094", but in c#, this value is "34434236"
It is the same value, 876823094 in hexadecimal notation is 0x34434236. Use Calc.exe, View + Programmer to see this for yourself. If you want to reproduce the same number that FSO gave you then you'll have to do the same thing it does and convert to base 10. Like this:
string hex = disk["VolumeSerialNumber"].ToString();
int value = int.Parse(hex, System.Globalization.NumberStyles.HexNumber, null);
string fso = value.ToString();
Check the solution in this thread.
The custom class HardDrive is used to store the retrieved information.
Get Hard Drive model
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach(ManagementObject wmi_HD in searcher.Get())
{
HardDrive hd = new HardDrive();
hd.Model = wmi_HD["Model"].ToString();
hd.Type = wmi_HD["InterfaceType"].ToString();
hdCollection.Add(hd);
}
The (minimum) class HardDrive
public class HardDrive
{
public string Model { get; set }
public string Type { get; set; }
}
Get the Serial Number
searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
int i = 0;
foreach(ManagementObject wmi_HD in searcher.Get())
{
// get the hard drive from collection
// using index
HardDrive hd = (HardDrive)hdCollection[i];
// get the hardware serial no.
if (wmi_HD["SerialNumber"] == null)
hd.SerialNo = "None";
else
hd.SerialNo = wmi_HD["SerialNumber"].ToString();
++i;
}
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;
}
I would like to determine the IP address of a printer, using C# (.NET 2.0). I have only the printer share name as set up on the Windows OS, in the format \\PC Name\Printer Name. The printer is a network printer, and has a different IP address to the PC. Does anyone have any pointers?
Thanks in advance for your help.
Regards, Andy.
Just adding an another solution here using .Net Framework 4.0 or higher
Using System.Printing
var server = new PrintServer();
var queues = server.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });
foreach (var queue in queues)
{
string printerName = queue.Name;
string printerPort = queue.QueuePort.Name;
}
Check this question: How to get Printer Info in C#.NET?. I think that you have to get the property PortName from the WMI properties.
I know this is an old post, but I had the same issue where I was able to get the Printer Port name, but not the IP. In my case I couldn't rely on the Port Name being IP_[IP Address] but found how to get hold of the actual IP from the port name.
Windows stores the information about ports in the registry under
HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\[port name]
This key contains the values set up in the port configuration page, including IP address and port number.
A quick C# example to get the IP address
using Microsoft.Win32;
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"System\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\" + printerPortName, RegistryKeyPermissionCheck.Default, System.Security.AccessControl.RegistryRights.QueryValues);
if (key != null)
{
String IP = (String)key.GetValue("IPAddress", String.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
}
Using WIN32_Printer class is not enough here. It should be combined with Win32_TCPIPPrinterPort class.
Below is the code which should help:
static void Main(string[] args)
{
var scope = new ManagementScope(#"\root\cimv2");
scope.Connect();
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer");
var results = searcher.Get();
Console.WriteLine("Network printers list:");
foreach (var printer in results)
{
var portName = printer.Properties["PortName"].Value;
var searcher2 = new ManagementObjectSearcher("SELECT * FROM Win32_TCPIPPrinterPort where Name LIKE '" + portName + "'");
var results2 = searcher2.Get();
foreach (var printer2 in results2)
{
Console.WriteLine("Name:" + printer.Properties["Name"].Value);
//Console.WriteLine("PortName:" + portName);
Console.WriteLine("PortNumber:" + printer2.Properties["PortNumber"].Value);
Console.WriteLine("HostAddress:" + printer2.Properties["HostAddress"].Value);
}
Console.WriteLine();
}
Console.ReadLine();
}
string printerName = "POS-80C";
LocalPrintServer server = new LocalPrintServer();
PrintQueue printQueue = server.GetPrintQueue(printerName);
string portName = printQueue.QueuePort.Name;
string portNumber = "";
string hostAddress = "";
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_TCPIPPrinterPort where Name LIKE '" + portName + "'");
var results = searcher.Get();
foreach (var printer in results)
{
portNumber = (printer.Properties["PortNumber"].Value).ToString();
hostAddress = (printer.Properties["HostAddress"].Value).ToString();
}
Is this printer set up in a network which has Active Directory?
Or is this on your own local network with just a switch and your printer plugged into it?
If it is the former, then you should be able to query for it based on the "printer name". This article show how to get c# .net to connect to the AD. But this does require some knowledge of AD servers in your network.
This solution seems a bit long to me, but may be a good starting point?
Based on the link How to get Printer Info in .NET? (Thanks, Panos, I was already looking at the link!), I have the following solution from Panos's answer:
using System.Management;
...
string printerName = "YourPrinterName";
string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}'", printerName);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection coll = searcher.Get();
foreach (ManagementObject printer in coll)
{
string portName = printer["PortName"].ToString();
if(portName.StartsWith("IP_"))
{
Console.WriteLine(string.Format("Printer IP Address: {0}", portName.Substring(3)));
}
}
Obviously, this only works if the port name for the printer is given in the format "IP_IPAddress", which is I believe is the default.