How to determine if drive is external drive - c#

How can I determine if a drive is a external drive plugged in through usb ? I checked the DriveInfo.DriveType but with my 1TB external drive plugged in through usb it shows up as a fixed drive.
Thoughts ?

Based on a comment from Floyd Pink I used this link. This allows me to determine whether a device is external or not.
public bool IsProjectOnExternalDisk(string driveLetter)
{
bool retVal = false;
driveLetter = driveLetter.TrimEnd('\\');
// browse all USB WMI physical disks
foreach (ManagementObject drive in new ManagementObjectSearcher("select DeviceID, MediaType,InterfaceType from Win32_DiskDrive").Get())
{
// associate physical disks with partitions
ManagementObjectCollection partitionCollection = new ManagementObjectSearcher(String.Format("associators of {{Win32_DiskDrive.DeviceID='{0}'}} " + "where AssocClass = Win32_DiskDriveToDiskPartition", drive["DeviceID"])).Get();
foreach (ManagementObject partition in partitionCollection)
{
if (partition != null)
{
// associate partitions with logical disks (drive letter volumes)
ManagementObjectCollection logicalCollection = new ManagementObjectSearcher(String.Format("associators of {{Win32_DiskPartition.DeviceID='{0}'}} " + "where AssocClass= Win32_LogicalDiskToPartition", partition["DeviceID"])).Get();
foreach (ManagementObject logical in logicalCollection)
{
if (logical != null)
{
// finally find the logical disk entry
ManagementObjectCollection.ManagementObjectEnumerator volumeEnumerator = new ManagementObjectSearcher(String.Format("select DeviceID from Win32_LogicalDisk " + "where Name='{0}'", logical["Name"])).Get().GetEnumerator();
volumeEnumerator.MoveNext();
ManagementObject volume = (ManagementObject)volumeEnumerator.Current;
if (driveLetter.ToLowerInvariant().Equals(volume["DeviceID"].ToString().ToLowerInvariant()) &&
(drive["MediaType"].ToString().ToLowerInvariant().Contains("external") || drive["InterfaceType"].ToString().ToLowerInvariant().Contains("usb")))
{
retVal = true;
break;
}
}
}
}
}
}
return retVal;
}
Using WMI Select * from Win32_LogicalDisk as in Royi Namir's answer and DriveInfo.DriveType show my external type as 'Local Disk' which I can't use to determine whether the drive is external.

you can use WMI
with
Select * from Win32_LogicalDisk
http://www.jpsoftwaretech.com/vba/using-wmi-services-in-vba/drive-information-local-network-mapped-drives/
there you have
Select Case .DriveType
Case 0
strDriveType = "Unknown"
Case 1
strDriveType = "No Root Directory"
Case 2
strDriveType = "Removable Disk"
Case 3
strDriveType = "Local Disk"
Case 4
strDriveType = "Network Drive"
Case 5
strDriveType = "Compact Disc"
Case 6
strDriveType = "RAM Disk"
End Select

I came across this question looking for a way to get a list of external drives, and I found that I could simplify a lot by updating the syntax. Also, some USB drives are UAS or USB attached SCSI, and the interface for those types of drives will actually show up as SCSI and not USB. From my tests, I've found that just checking for the terms "external" and "removable" in the physical disk's media type is sufficient.
public List<DriveInfo> getExternalDrives()
{
var drives = DriveInfo.GetDrives();
var externalDrives = new List<DriveInfo>();
var allPhysicalDisks = new ManagementObjectSearcher("select MediaType, DeviceID from Win32_DiskDrive").Get();
foreach (var physicalDisk in allPhysicalDisks)
{
var allPartitionsOnPhysicalDisk = new ManagementObjectSearcher($"associators of {{Win32_DiskDrive.DeviceID='{physicalDisk["DeviceID"]}'}} where AssocClass = Win32_DiskDriveToDiskPartition").Get();
foreach(var partition in allPartitionsOnPhysicalDisk)
{
if (partition == null)
continue;
var allLogicalDisksOnPartition = new ManagementObjectSearcher($"associators of {{Win32_DiskPartition.DeviceID='{partition["DeviceID"]}'}} where AssocClass = Win32_LogicalDiskToPartition").Get();
foreach(var logicalDisk in allLogicalDisksOnPartition)
{
if (logicalDisk == null)
continue;
var drive = drives.Where(x => x.Name.StartsWith(logicalDisk["Name"] as string, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
var mediaType = (physicalDisk["MediaType"] as string).ToLowerInvariant();
if (mediaType.Contains("external") || mediaType.Contains("removable"))
externalDrives.Add(drive);
}
}
}
return externalDrives;
}

Related

Retrieve LoggedOnUsers on Remote Machine

I'm building a C# application to monitor server and workstation workloads with WMI and WQL queries. I'm using WMI because it seems to be faster in comparison to powershell queries. My hardship starts when I try to retrieve logged on users on a remote machine. I figured I need to use the Win32_LoggedOnUser class. I have tried the following queries:
#"SELECT * FROM Win32_LoggedOnUser"
#"SELECT Antecedent FROM Win32_LoggedOnUser"
What I'm used to is to retrieve the desired value like this:
var cims = connection.getCimInstances(this, queryUser);
if (cims != null)
{
foreach (CimInstance cim in cims)
{
Komponenten.User user = new Komponenten.User();
user.Name = Convert.ToString(cim.CimInstanceProperties["Name"].Value);
users.Add(user);
}
}
where queryUser is one of the strings from above.
In both cases, I get a Win32_Account object in return, which seems to suggest - and the debugger seems to confirm - that I should use CimInstanceProperties["Name"].Value on the returned Win32_Account class again. But that's not working at all. Any ideas on how to get access to the CimInstanceProperties of a Win32_Account stored in a CimInstanceProperity ? I can't find anything on the respective Windows reference page (https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-loggedonuser) nor during my extensive google-search.
Thanks!
I ended up using the ManagementObject-Class and Regex to find the usernames after converting the Antecedent - Object to a string:
var users = new List<Komponenten.User>();
var searcher = this.connection.makeQuery(this, "SELECT * FROM Win32_LoggedOnUser");
if (searcher != null)
{
foreach (ManagementObject queryObj in searcher.Get())
{
Komponenten.User user = new Komponenten.User();
var win32_account = queryObj["Antecedent"].ToString();
string stripped = Regex.Replace(win32_account, "[^a-zA-Z=]+", "", RegexOptions.Compiled);
int end = stripped.LastIndexOf("=");
user.Name = stripped.Substring(end+1);
users.Add(user);
}
this.users = users;
An alternative which takes the LogonSession into account is:
var users = new List<Komponenten.User>();
var searcher = this.connection.makeQuery(this, "SELECT LogonId FROM Win32_LogonSession Where LogonType=2");
var Scope = this.connection.getScope(this, this.connection.getConnection());
if (searcher != null)
{
foreach (ManagementObject queryObj in searcher.Get())
{
ObjectQuery LQuery = new ObjectQuery("Associators of {Win32_LogonSession.LogonId=" + queryObj["LogonId"] + "} Where AssocClass=Win32_LoggedOnUser Role=Dependent");
ManagementObjectSearcher LSearcher = new ManagementObjectSearcher(Scope, LQuery);
foreach (ManagementObject LWmiObject in LSearcher.Get())
{
Komponenten.User user = new Komponenten.User();
user.Name = Convert.ToString(LWmiObject["Name"]);
users.Add(user);
}
}
this.users = users;
}
where this.connection.getConnection is a ConnectionsOption object depending on your respective domain and account data

How to get Availability from Win32_PnPEntity

I am trying to get the availability status from a PnP device
I have read through this article: Win32_PnPEntity , and it seems like I should be able to get the value; however it always comes up null and I can't figure out why. Other properties like "Name", "Caption", "ClassGUID", etc are returning good values.
Here is some code showing what I'm trying to do...
ManagementObjectCollection collection;
using (var searcher = new ManagementObjectSearcher(#"SELECT * FROM Win32_PnPEntity WHERE Description LIKE '%USB%'"))
collection = searcher.Get();
Console.WriteLine("Waiting for CmdPort to be available...");
foreach(device in collection)
{
var availableTimeout = 50;
while (availableTimeout > 0)
{
var availability = device["Availability"] ?? -1;
if((int)availability == 3)
break;
Console.WriteLine($"Availability = {availability.ToString()} (timeout = {availableTimeout})")
availableTimeout--;
Thread.Sleep(100);
}
}
I'm expecting availability to come back with a uint16 between 1 and 21

Listing network printers

Trying to run the following (found here http://www.encodedna.com/2013/04/show-printers-using-wmi.htm ) to get a list of network printers but it only returns printers added to my machine
System.Management.ManagementScope objMS = new System.Management.ManagementScope(ManagementPath.DefaultPath);
objMS.Connect();
SelectQuery objQuery = new SelectQuery("SELECT * FROM Win32_Printer");
ManagementObjectSearcher objMOS = new ManagementObjectSearcher(objMS, objQuery);
System.Management.ManagementObjectCollection objMOC = objMOS.Get();
foreach (ManagementObject Printers in objMOC)
{
if (Convert.ToBoolean(Printers["Local"])) // LOCAL PRINTERS.
{
Console.WriteLine("Local :- " + Printers["Name"]);
}
if (Convert.ToBoolean(Printers["Network"])) // ALL NETWORK PRINTERS.
{
Console.WriteLine("Network :- " + Printers["Name"]);
}
}
I can view/add network printers in control panel. Just curious why it isn't showing them. Any thoughts?
Thanks!
Try:
foreach (string printerString in PrinterSettings.InstalledPrinters)
{
// do something
}

How to get hard drive unique serial number in C#

I develop an activation for a system. to generate request code, I used HDD ID, Bios ID and Processor ID. I used following code to get hard disk ID.
private string getHardDiskID()
{
string hddID = null;
ManagementClass mc = new ManagementClass("Win32_LogicalDisk");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject strt in moc)
{
hddID += Convert.ToString(strt["VolumeSerialNumber"]);
}
return hddID.Trim().ToString();
}
But if I plug a removable disk, That ID value is changed. How to get the UNIQUE Serial Number of the hard drive...?
Thanks in advance..
You can try from this source:
As said in the source, a better solution is to get the Hard Drive Serial Number given by the Manufacturer. This value won't change even if you format your Hard Drive.
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;
}
ManagementObjectSearcher searcher;
searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
string serial_number="";
foreach (ManagementObject wmi_HD in searcher.Get())
{
serial_number = wmi_HD["SerialNumber"].ToString();
}
MessageBox.Show(serial_number);
Check below code to get HDD Serial
ManagementObjectSearcher objSearcher = new
ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
objSearcher = new
ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
int i = 0;
foreach(ManagementObject wmi_HD in objSearcher.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;
}
Also You can type "wbemtest" in windows run. WBEMTEST is tool which
helps in running WQL queries.

Detecting if disc is in DVD drive

Is there an easy way to detect if a disc is inserted in the DVD drive? I don't care what kind of disc (CD, DVD or Blu-Ray)?
Use WMI to detect if disk in CD/DVD drive:
foreach (var drive in DriveInfo.GetDrives()
.Where(d => d.DriveType == DriveType.CDRom))
MessageBox.Show(drive.Name + " " + drive.IsReady.ToString());
from here.
DriveType Enumeration can help you what kind of disc:
CDRom : The drive is an optical disc device, such as a CD or DVD-ROM.
Fixed : The drive is a fixed disk.
Network : The drive is a network drive.
NoRootDirectory The drive does not have a root directory.
Ram : The drive is a RAM disk.
Removable : The drive is a removable storage device, such as a floppy disk drive or a USB flash drive.
Unknown : The type of drive is unknown.
for kind of CD/DVD/Blue-Ray see IMAPI_MEDIA_PHYSICAL_TYPE enumeration:
UNKNOWN
CDROM
CDR
CDRW
DVDROM
DVDRAM
DVDPLUSR
DVDPLUSRW
DVDPLUSR_DUALLAYER
DVDDASHR
DVDDASHRW
DVDDASHR_DUALLAYER
DISK
DVDPLUSRW_DUALLAYER
HDDVDROM
HDDVDR
HDDVDRAM
BDROM
BDR
BDRE
MAX
your code may be like this:
public bool IsDiscAvailable(int driveNumber)
{
MsftDiscMaster2Class discMaster = new MsftDiscMaster2Class();
string id = discMaster[driveNumber];
MsftDiscRecorder2Class recorder = new MsftDiscRecorder2Class();
recorder.InitializeDiscRecorder(id);
MsftDiscFormat2DataClass dataWriter = new MsftDiscFormat2DataClass();
if (dataWriter.IsRecorderSupported(recorder))
{
dataWriter.Recorder = recorder;
}
else
{
Console.WriteLine("Recorder not supported");
return false;
}
if (dataWriter.IsCurrentMediaSupported(recorder))
{
var media = dataWriter.CurrentPhysicalMediaType;
if (media == IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN)
{
Console.WriteLine("Unknown media or no disc");
}
else
{
Console.WriteLine("Found disc type {0}", media);
return true;
}
}
else
{
Console.WriteLine("Disc absent or invalid.");
}
return false;
}
from here.
How to Detect CD-ROM is loaded in the CD-ROM drive
From above link
using System;
using System.Management;
class Application
{
public static void Main()
{
SelectQuery query =
new SelectQuery( "select * from win32_logicaldisk where drivetype=5" );
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(query);
foreach( ManagementObject mo in searcher.Get() )
{
// If both properties are null I suppose there's no CD
if(( mo["volumename"] != null) || (mo["volumeserialnumber"] != null))
{
Console.WriteLine("CD is named: {0}", mo["volumename"]);
Console.WriteLine("CD Serial Number: {0}", mo["volumeserialnumber"]);
}
else
{
Console.WriteLine("No CD in Unit");
}
}
// Here to stop app from closing
Console.WriteLine("\nPress Return to exit.");
Console.Read();
}
}

Categories

Resources