C# WMI MSFT_Disk syntax - c#

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

Related

List Of Hard Disks and drives on them

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/

Retrieving disc serial id gives me different values using FSO or ManagementObject

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

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

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.

webbrowser not refreshing stylesheet

I post the complete code below, so you can see what I'm doing.
Situation:
I create a IHTMLDocument2 currentDoc pointing to the DomDocument
I write the proper string
I close the currentDoc
program shows me the html code including the CSS stuff 100% correct. Works
Now I want to change the CSS, instead of 2 columns I set it to 3 columns
(Simply change the width:48% to width:33%)
and rerun the code with the new 33%
now it suddenly doesn't apply any CSS style anymore.
When I close the program, and then change the CSS to 33% again, it works flawless
So, somehow, without disposing the complete webbrowser, I can't load the CSS a 2nd time..
or, the first CSS is somewhere in some cache, and conflicts with the 2nd CSS.. Just riddling here.. really need help on how to solve this
I searched the internet and stackoverflow long enough that I need to post this, even if someone else on this planet already posted it somewhere, I didn't find it.
private void doWebBrowserPreview()
{
if (lMediaFiles.Count == 0)
{
return;
}
Int32 iIndex = 0;
for (iIndex = 0; iIndex < lMediaFiles.Count; iIndex++)
{
if (!lMediaFiles[iIndex].isCorrupt())
{
break;
}
}
String strPreview = String.Empty;
String strLine = String.Empty;
// Set example Media
String strLinkHTM = lMediaFiles[iIndex].getFilePath();
FileInfo movFile = new FileInfo(strLinkHTM + lMediaFiles[iIndex].getFileMOV());
String str_sizeMB = (movFile.Length / 1048576).ToString();
if (str_sizeMB.Length > 3)
{
str_sizeMB.Insert(str_sizeMB.Length - 3, ".");
}
//Get info about our media files
MediaInfo MI = new MediaInfo();
MI.Open(strLinkHTM + lMediaFiles[iIndex].getFileM4V());
String str_m4vDuration = // MI.Get(0, 0, 80);
MI.Get(StreamKind.Video, 0, 74);
str_m4vDuration = "Duration: " + str_m4vDuration.Substring(0, 8) + " - Hours:Minutes:Seconds";
String str_m4vHeightPixel = MI.Get(StreamKind.Video, 0, "Height"); // "Height (Pixel): " +
Int32 i_32m4vHeightPixel;
Int32.TryParse(str_m4vHeightPixel, out i_32m4vHeightPixel);
i_32m4vHeightPixel += 16; // for the quicktime embed menu
str_m4vHeightPixel = i_32m4vHeightPixel.ToString();
String str_m4vWidthPixel = MI.Get(StreamKind.Video, 0, "Width"); //"Width (Pixel): " +
foreach (XElement xmlLine in s.getTemplates().getMovieHTM().Element("files").Elements("file"))
{
var query = xmlLine.Attributes("type");
foreach (XAttribute result in query)
{
if (result.Value == "htm_header")
{
foreach (XElement xmlLineDes in xmlLine.Descendants())
{
if (xmlLineDes.Name == "dataline")
{
strLine = xmlLineDes.Value;
strLine = strLine.Replace(#"%date%", lMediaFiles[iIndex].getDay().ToString() + " " + lMediaFiles[iIndex].getMonth(lMediaFiles[iIndex].getMonth()) + " " + lMediaFiles[iIndex].getYear().ToString());
strPreview += strLine + "\n";
}
}
}
}
}
strLine = "<style type=\"text/css\">" + "\n";
foreach (XElement xmlLine in s.getTemplates().getLayoutCSS().Element("layoutCSS").Elements("layout"))
{
var query = xmlLine.Attributes("type");
foreach (XAttribute result in query)
{
if (result.Value == "layoutMedia")
{
foreach (XElement xmlLineDes in xmlLine.Elements("layout"))
{
var queryL = xmlLineDes.Attributes("type");
foreach (XAttribute resultL in queryL)
{
if (resultL.Value == "layoutVideoBox")
{
foreach (XElement xmlLineDesL in xmlLineDes.Descendants())
{
if (xmlLineDesL.Name == "dataline")
{
strLine += xmlLineDesL.Value + "\n";
}
}
}
}
}
}
}
}
strLine += "</style>" + "\n";
strPreview = strPreview.Insert(strPreview.LastIndexOf("</head>", StringComparison.Ordinal), strLine);
for (Int16 i16Loop = 0; i16Loop < 3; i16Loop++)
{
foreach (XElement xmlLine in s.getTemplates().getMovieHTM().Element("files").Elements("file"))
{
var query = xmlLine.Attributes("type");
foreach (XAttribute result in query)
{
if (result.Value == "htm_videolist")
{
foreach (XElement xmlLineDes in xmlLine.Descendants())
{
if (xmlLineDes.Name == "dataline")
{
strLine = xmlLineDes.Value;
strLine = strLine.Replace(#"%m4vfile%", strLinkHTM + lMediaFiles[iIndex].getFileM4V());
strLine = strLine.Replace(#"%moviefile%", strLinkHTM + lMediaFiles[iIndex].getFileMOV());
strLine = strLine.Replace(#"%height%", str_m4vHeightPixel);
strLine = strLine.Replace(#"%width%", str_m4vWidthPixel);
strLine = strLine.Replace(#"%duration%", str_m4vDuration);
strLine = strLine.Replace(#"%sizeMB%", str_sizeMB);
strLine = strLine.Replace(#"%date%", lMediaFiles[iIndex].getDay().ToString() + " " + lMediaFiles[iIndex].getMonth(lMediaFiles[iIndex].getMonth()) + " " + lMediaFiles[iIndex].getYear().ToString());
strPreview += strLine + "\n";
}
}
}
}
}
}
foreach (XElement xmlLine in s.getTemplates().getMovieHTM().Element("files").Elements("file"))
{
var query = xmlLine.Attributes("type");
foreach (XAttribute result in query)
{
if (result.Value == "htm_footer")
{
foreach (XElement xmlLineDes in xmlLine.Descendants())
{
if (xmlLineDes.Name == "dataline")
{
strPreview += xmlLineDes.Value + "\n";
}
}
}
}
}
webBrowserPreview.Navigate("about:blank");
webBrowserPreview.Document.OpenNew(false);
mshtml.IHTMLDocument2 currentDoc = (mshtml.IHTMLDocument2)webBrowserPreview.Document.DomDocument;
currentDoc.clear();
currentDoc.write(strPreview);
currentDoc.close();
/*
try
{
if (webBrowserPreview.Document != null)
{
IHTMLDocument2 currentDocument = (IHTMLDocument2)webBrowserPreview.Document.DomDocument;
int length = currentDocument.styleSheets.length;
IHTMLStyleSheet styleSheet = currentDocument.createStyleSheet(#"", 0);
//length = currentDocument.styleSheets.length;
//styleSheet.addRule("body", "background-color:blue");
strLine = String.Empty;
foreach (XElement xmlLine in s.getTemplates().getLayoutCSS().Element("layoutCSS").Elements("layout"))
{
var query = xmlLine.Attributes("type");
foreach (XAttribute result in query)
{
if (result.Value == "layoutMedia")
{
foreach (XElement xmlLineDes in xmlLine.Elements("layout"))
{
var queryL = xmlLineDes.Attributes("type");
foreach (XAttribute resultL in queryL)
{
if (resultL.Value == "layoutVideoBox")
{
foreach (XElement xmlLineDesL in xmlLineDes.Descendants())
{
if (xmlLineDesL.Name == "dataline")
{
strLine += xmlLineDesL.Value;
}
}
}
}
}
}
}
}
//TextReader reader = new StreamReader(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "basic.css"));
//string style = reader.ReadToEnd();
styleSheet.cssText = strLine;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}*/
webBrowserPreview.Refresh();
}
I now successfully implemented the berkelium-sharp method to my project
Has the same bug!
Found a solution!
First attempt which didn't work:
I had a persistent form (main form) and inside it a nested WebBrowser.
After changing the html with it's css, i told it to navigate to this new html!
This didn't work either:
Then I tried putting webbrowser on an own form. Which I simply open/close each
time I need a refresh. TO be sure the garbage collector cleans everything
Then I tried the Berkelium and rewrote it to my needs:
same logic as attempt 2 with the webbrowser. No luck either.
So I tried to open firefox itself and see if I can emulate this behaviour with a real browser. Indeed! When I open firefox, and force open the file (if you simply open a new file, firefox doesn't actually navigate to it, but detects this was already opened and simply refreshes it)
I noticed this due to the fast opening of the page!
A little scripting to force opening the same file twice (navigating) in 1 firefox session had the same effect: all CSS corrupt!
so, for some reason, you shouldn't navigate the same file twice, but instead of closing anything, simply force a refresh! Not a "Navigate"
Hope this info can help others, since I lost a lot of time finding out that it is the "navigate" to the same file more then once causing the corruption of stylesheets

Categories