List Of Hard Disks and drives on them - c#

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/

Related

C# WMI MSFT_Disk syntax

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

foreach (ManagementObject user in users) doesn't seem to be retrieving all local accounts

I use the following method to get all LOCAL user accounts on a machine. It finds 12 of them, but only processes the first one.
ObjectQuery wql = new ObjectQuery(#"SELECT * FROM Win32_UserProfile");
ManagementObjectSearcher usersSearcher = new ManagementObjectSearcher(wql);
ManagementObjectCollection users = usersSearcher.Get();
Console.WriteLine("Users: " + "[" + users.Count + "]"); // Reports 12
foreach (ManagementObject user in users)
{
Console.WriteLine("Checking User: " + GetNameFromSID(user["SID"].ToString()));
}
It seems that it used to report all accounts. Is there a surefire way to get this information?

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;
}

How to get the description of a running process on a remote machine?

I have tried two ways to accomplish this so far.
The first way, I used System.Diagnostics, but I get a NotSupportedException of "Feature is not supported for remote machines" on the MainModule.
foreach (Process runningProcess in Process.GetProcesses(server.Name))
{
Console.WriteLine(runningProcess.MainModule.FileVersionInfo.FileDescription);
}
The second way, I attempted using System.Management but it seems that the Description of the ManagementObject is the she same as the Name.
string scope = #"\\" + server.Name + #"\root\cimv2";
string query = "select * from Win32_Process";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection collection = searcher.Get();
foreach (ManagementObject obj in collection)
{
Console.WriteLine(obj["Name"].ToString());
Console.WriteLine(obj["Description"].ToString());
}
Would anyone happen to know of a better way to go about getting the descriptions of a running process on a remote machine?
Well I think I've got a method of doing this that will work well enough for my purposes. I'm basically getting the file path off of the ManagementObject and getting the description from the actual file.
ConnectionOptions connection = new ConnectionOptions();
connection.Username = "username";
connection.Password = "password";
connection.Authority = "ntlmdomain:DOMAIN";
ManagementScope scope = new ManagementScope(#"\\" + serverName + #"\root\cimv2", connection);
scope.Connect();
ObjectQuery query = new ObjectQuery("select * from Win32_Process");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection collection = searcher.Get();
foreach (ManagementObject obj in collection)
{
if (obj["ExecutablePath"] != null)
{
string processPath = obj["ExecutablePath"].ToString().Replace(":", "$");
processPath = #"\\" + serverName + #"\" + processPath;
FileVersionInfo info = FileVersionInfo.GetVersionInfo(processPath);
string processDesc = info.FileDescription;
}
}

How can I check for available disk space?

I need a way to check available disk space on a remote Windows server before copying files to that server. Using this method I can check to see if the primary server is full and if it is, then I'll copy the files to a secondary server.
How can I check for available disk space using C#/ASP.net 2.0?
You can check it by doing the following:
Add the System.Management.dll as a reference to your project.
Use the following code to get the diskspace:
using System;
using System.Management;
public string GetFreeSpace();
{
ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"c:\"");
disk.Get();
string freespace = disk["FreeSpace"];
return freespace;
}
There are a myriad of ways to do it, I'd check the System.Management namespace for more ways.
Here's one such way from that page:
public void GetDiskspace()
{
ConnectionOptions options = new ConnectionOptions();
ManagementScope scope = new ManagementScope("\\\\localhost\\root\\cimv2",
options);
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
SelectQuery query1 = new SelectQuery("Select * from Win32_LogicalDisk");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
ManagementObjectSearcher searcher1 = new ManagementObjectSearcher(scope, query1);
ManagementObjectCollection queryCollection1 = searcher1.Get();
foreach (ManagementObject m in queryCollection)
{
// Display the remote computer information
Console.WriteLine("Computer Name : {0}", m["csname"]);
Console.WriteLine("Windows Directory : {0}", m["WindowsDirectory"]);
Console.WriteLine("Operating System: {0}", m["Caption"]);
Console.WriteLine("Version: {0}", m["Version"]);
Console.WriteLine("Manufacturer : {0}", m["Manufacturer"]);
Console.WriteLine();
}
foreach (ManagementObject mo in queryCollection1)
{
// Display Logical Disks information
Console.WriteLine(" Disk Name : {0}", mo["Name"]);
Console.WriteLine(" Disk Size : {0}", mo["Size"]);
Console.WriteLine(" FreeSpace : {0}", mo["FreeSpace"]);
Console.WriteLine(" Disk DeviceID : {0}", mo["DeviceID"]);
Console.WriteLine(" Disk VolumeName : {0}", mo["VolumeName"]);
Console.WriteLine(" Disk SystemName : {0}", mo["SystemName"]);
Console.WriteLine("Disk VolumeSerialNumber : {0}", mo["VolumeSerialNumber"]);
Console.WriteLine();
}
string line;
line = Console.ReadLine();
}
by using this code
static void Main()
{
try
{
DriveInfo driveInfo = new DriveInfo(#"C:");
long FreeSpace = driveInfo.AvailableFreeSpace;
}
catch (System.IO.IOException errorMesage)
{
Console.WriteLine(errorMesage);
}
}
IF you are getting the error 'The device is not ready' .i.e your device is not ready .
If you are trying this code for a CD drive without CD you will get the same error : )
This seems to be an option from the System.IO:
DriveInfo c = new DriveInfo("C");
long cAvailableSpace = c.AvailableFreeSpace;
You can use the DriveInfo class
DriveInfo[] oDrvs = DriveInfo.GetDrives();
foreach (var Drv in oDrvs) {
if (Drv.IsReady) {
Console.WriteLine(Drv.Name + " " + Drv.AvailableFreeSpace.ToString);
}
}
You can use WMI, see this related question:
Best way to query disk space on remote server

Categories