Obtaining HDD Serial Number via Drive Letter using WMI query in C# - c#

I have the following code which works well in obtaining HDD serial numbers via the Model string value in Win32_DiskDrive. But I need to obtain the serial number via the drive letter assigned. Is this possible? If so how?
public string GetDriveSerial(string model)
{
string serial = string.Empty;
string query = "SELECT * FROM Win32_DiskDrive WHERE Model = '" + model + "'";
try
{
using (var results = new ManagementObjectSearcher("root\\CIMV2", query))
{
foreach (ManagementObject result in results.Get())
{
serial = result["SerialNumber"].ToString();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return serial;
}

You can try this:
public static string GetSerialFromDrive(string driveLetter)
{
try
{
using (var partitions = new ManagementObjectSearcher("ASSOCIATORS OF {Win32_LogicalDisk.DeviceID='" + driveLetter +
"'} WHERE ResultClass=Win32_DiskPartition"))
{
foreach (var partition in partitions.Get())
{
using (var drives = new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" +
partition["DeviceID"] +
"'} WHERE ResultClass=Win32_DiskDrive"))
{
foreach (var drive in drives.Get())
{
return (string)drive["SerialNumber"];
}
}
}
}
}
catch
{
return "<unknown>";
}
// Not Found
return "<unknown>";
}
This expects the drive letter like this: "C:", "D:" ...
The original code can be found here.

Related

How do I identify a paired Bluetooth device that's currently disconnected?

How do I discover a paired Bluetooth device that's currently disconnected?
I've attempted the following code using the Windows 10 SDK:
using Windows.Devices.Enumeration;
using Windows.Devices.Bluetooth.Rfcomm;
var serviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
I've also tried the following:
using System;
using System.Diagnostics;
using System.Management;
public class Win32_UsbDriveWatcher
{
ManagementEventWatcher m_watcher;
public delegate void DeviceInsertedEventHandler(object sender, Win32_UsbDriveInsertEventArgs e);
public event DeviceInsertedEventHandler DeviceInserted;
public event EventHandler DeviceRemoved;
public void Start(int pollingInterval)
{
try
{
var queryString =
"SELECT * " +
" FROM __InstanceOperationEvent" +
" WITHIN " + pollingInterval +
" WHERE TargetInstance ISA 'Win32_PnPEntity'";
var processQuery = new EventQuery(queryString);
m_watcher = new ManagementEventWatcher(processQuery);
m_watcher.EventArrived += EventArrived;
m_watcher.Start();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
void EventArrived(object sender, EventArrivedEventArgs e)
{
var instance = ((PropertyData)(e.NewEvent.Properties["TargetInstance"]));
var obj = (ManagementBaseObject)instance.Value;
var args = new Win32_UsbDriveInsertEventArgs();
if ((string)obj["InterfaceType"] == "BLUETOOTH")
{
args.IsCreated = (obj.ClassPath.ClassName == "__InstanceCreationEvent");
args.DriveName = GetDriveLetterFromDisk((string)obj["Name"]);
if (args.IsCreated)
{
DeviceInserted?.Invoke(this, args);
}
else
{
DeviceRemoved?.Invoke(this, EventArgs.Empty);
}
}
}
static string GetDriveLetterFromDisk(string name)
{
name = name.Replace("\\", "\\\\");
var query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + name + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
var queryDrive = new ObjectQuery(query);
using (var searcherDrive = new ManagementObjectSearcher(queryDrive))
{
foreach (ManagementObject drive in searcherDrive.Get())
{
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" +
drive["DeviceID"] +
"'} WHERE AssocClass = Win32_LogicalDiskToPartition";
var queryPartition = new ObjectQuery(query);
using (var searcherPartition = new ManagementObjectSearcher(queryPartition))
{
foreach (ManagementObject disk in searcherPartition.Get())
{
return (string)disk["Name"];
}
}
}
return string.Empty;
}
}
}
public class Win32_UsbDriveInsertEventArgs : EventArgs
{
public bool IsCreated;
public string DriveName;
}
Regardless of the code snippets that I've attempted, I'm still unable to discover paired disconnected devices.
Any suggestions?
There are few way:
Use WM_DEVICE_CHANGE message to know when device connected and disconnected.
Once you found all paired devices query each for its services. Not available (disconnected) device reports error.
Try to connect to device's SDP service using DeviceIOControl (the best way).

WMI Query Library C#

I am having hard time understanding why there's not a single WMI query library
in here or google pointed out. Simply interface to query WMI for information. All I can find is "write a new query like this..."-style of topics all over web which makes no sense to me while there's few hundred queries I am working with.
So, here's my current effort building one:
using System;
using System.Management;
namespace hardware
{
public class Info
{
public static Tuple<string[], int, int> Query(string Select, string From, string Where = null, string Answer = null, string Root = "root\\CIMV2")
{
int Count = 0;
string[] Values = Select.Split(',');
if (Where != null && Answer != null)
{
ManagementObjectSearcher s = new ManagementObjectSearcher(Root, "SELECT " + Select + " FROM " + From + " WHERE " + Where + " = '" + Answer + "'");
string[] res = new string[Values.Length];
foreach (ManagementObject wQuery in s.Get())
{
foreach (string value in Values)
{
res[Count] = Convert.ToString(wQuery[value]);
Count++;
}
}
var result = new Tuple<string[], int, int> (res, Values.Length, Count);
return result;
}
else
{
ManagementObjectSearcher s = new ManagementObjectSearcher(Root, "SELECT " + Select + " FROM " + From);
string[] res = new string[Values.Length];
foreach (ManagementObject wQuery in s.Get())
{
foreach (string value in Values)
{
res[Count] = Convert.ToString(wQuery[value]);
Count++;
}
}
var result = new Tuple<string[], int, int>(res, Values.Length, Count);
return result;
}
}
}
}
I've been trying to get above in working order now for a weeks. Coming from basic string multi-dimensional array (return string[,] or string[][]) just started testing, if returning tuple (which I used few years ago successfully) would be better choice.
So, anyone know, if there is library already written?
if not, then best way to do above query from reference DLL library?
I know this question is old. But you can use ORMi library. I think it will just fit on your needs.
For example:
1) Define your class:
[WMIClass("Win32_Processor")]
public class Processor
{
public string Name { get; set; }
[WMIProperty("NumberOfCores")]
public int Cores { get; set; }
public string Description { get; set; }
}
2) Query:
WMIHelper helper = new WMIHelper("root\\CimV2");
List<Processor> processors = helper.Query<Processor>().ToList();
3) Or lazy coding option:
var processors = helper.Query("SELECT * FROM Win32_Processor");
You can find more information in here:
https://github.com/nicoriff/ORMi
https://medium.com/#luque.nicolas/compare-ormi-and-traditional-net-wmi-implementation-f00db26d10a3

Listing Local Administrators on a Remote Machine with WMI

I am able to get a list of members of the 'Administrators' group on a remote machine with this function:
public IEnumerable<string> GroupMembers(string groupname)
{
var result = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
try
{
var qs = new StringBuilder();
qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='");
qs.Append(_machineName);
qs.Append("',Name='");
qs.Append(groupname);
qs.AppendLine("'\"");
var query = new ObjectQuery(qs.ToString()); // SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = "Win32_Group.Domain='MYMACHINENAME',Name='Administrators'"
var searcher = new ManagementObjectSearcher(_scope, query);
var queryCollection = searcher.Get();
foreach (var m in queryCollection)
{
var path = new ManagementPath(m["PartComponent"].ToString());
{
var names = path.RelativePath.Split(',');
result.Add(names[0].Substring(names[0].IndexOf("=") + 1).Replace("\"", " ").Trim() + "\\" + // Win32_UserAccount.Domain=xxxxxx
names[1].Substring(names[1].IndexOf("=") + 1).Replace("\"", " ").Trim()); // Name=xxxxx
}
}
return result; // MYMACHINENAME\Administrator,MYDOMAIN\Domain Admins,MYDOMAIN\Dev Service Accounts
}
catch (Exception e)
{
_logger.Error("Message: " + e.Message);
throw;
}
}
However, this does not expand the groups returned to list all the individual members. This is effectively the same as net localgroup Administrators.
In my example, I'm looking to see if one of the members of MYDOMAIN\Dev Service Accounts is an administrator.
How can I adjust my WMI query to expand all the groups to a flat list of usernames?

Network not found Exceptions

I am trying to find a txt files over computers of a domain network.
What I have done till now:
I have the list of all computers of the domain in an array.So I am iterating each computer with its corresponding address with the help of getfile command.
Where I am stuck :
There are some computers over which I don't have access.So my search is either taking a long time to leap those exceptions or it gets struck at some point.As there are more that 500 systems so I want to increase the speed and accuracy of my program.
I am mostly getting network not found error.
Here is my code:
namespace ABC
{
class Program
{
static void Main(string[] args)
{
List<string> cnames=new List<string>();
DirectoryEntry entry = new DirectoryEntry("LDAP://abc.com", "username", "password", AuthenticationTypes.Secure);
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(objectClass=computer)");
foreach (SearchResult resEnt in mySearcher.FindAll())
{
string name = resEnt.GetDirectoryEntry().Name;
if (name.StartsWith("CN="))
name = name.Remove(0, "CN=".Length);
cnames.Add(name);
}
int cnumbers=cnames.Count;
for (int i = 0; i < cnumbers;i++ )
{
string s = "\\\\" + cnames[i] + "\\ab\\cd";
string[] dirs = null;
Console.WriteLine("Name of Computer=" + cnames[i]);
try
{
dirs = Directory.GetFiles(s);
try
{
foreach (string dir in dirs)
{
Console.WriteLine(dir);
}
}
catch (Exception e)
{
}
}
catch (Exception)
{
}
}
}
}
}

Find Hard Disk Serial number from Remote SQL Server Installed Hard disk

I have a C#.net Windows form Application with SQL Server. My application use in Multiple user by local Network. Now I need to find Hard disk Serial Number which hard disk installed sql server (Note: By Using C#.net Application Data source ).
How can i find Hard disk Serial number throw by application data source?
This might be useful
using System;
using System.Management;
using System.Collections;
namespace WmiControl
{
public class WMI
{
public bool GetDiskSerial(string Computername)
{
try
{
ManagementScope scope = new ManagementScope(#"\\" + Computername + #"\root\cimv2");
scope.Connect();
ArrayList hdCollection;
ManagementObjectSearcher searcher;
if (GetDiskDrive(scope, out hdCollection, out searcher) || GetDiskSerial(scope, hdCollection, ref searcher))
return true;
else
return false;
}
catch (ManagementException)
{
return false;
}
}
private bool GetDiskSerial(ManagementScope scope, ArrayList hdCollection, ref ManagementObjectSearcher searcher)
{
try
{
ObjectQuery query1 = new ObjectQuery("SELECT * FROM Win32_PhysicalMedia");
searcher = new ManagementObjectSearcher(scope, query1);
int i = 0;
string sDiskSerial = "";
foreach (ManagementObject wmi_HD in searcher.Get())
{
// get the hard drive from collection
// using index
if (i < hdCollection.Count)
{
HardDrive hd = (HardDrive)hdCollection[i];
if (wmi_HD["SerialNumber"] == null)
hd.SerialNo = "";
else
hd.SerialNo = wmi_HD["SerialNumber"].ToString();
}
++i;
}
foreach (HardDrive hd in hdCollection)
{
if (!String.IsNullOrEmpty(hd.SerialNo))
{
sDiskSerial = hd.SerialNo;
break;
}
}
return true;
}
catch (Exception)
{
return false;
}
}
private bool GetDiskDrive(ManagementScope scope, out ArrayList hdCollection, out ManagementObjectSearcher searcher)
{
try
{
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_DiskDrive");
hdCollection = new ArrayList();
searcher = new ManagementObjectSearcher(scope, query);
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);
return true;
}
return true;
}
catch (Exception)
{
hdCollection = null;
searcher = null;
return false;
}
}
}
class HardDrive
{
private string model = null;
private string type = null;
private string serialNo = null;
public string Model
{
get { return model; }
set { model = value; }
}
public string Type
{
get { return type; }
set { type = value; }
}
public string SerialNo
{
get { return serialNo; }
set { serialNo = value; }
}
}
}
See here for more info
You might want also to study CLR
You'll need to resort to WMI. With the proper privileges on the SQL Server machine, you can get the serial number of the hard-drives on it. See here for an example on retrieving the hard-disk's serial number using WMI.
You'll need to figure out which disk holds SQL Server and how to access the SQL Server machine on your own.
You have to do it in 3 stages:
The connection string of the data source gives you the name of the machine on which SQL Server is installed
You must then query the machine to find out the drive which drive SQL Server is installed on
You can then use the code supplied by others here to get the serial number

Categories

Resources