Hello I've got a bit of a problem. I'm trying to use WMI to list information about disks. When I run the code from the WMI code creator everything returns fine and I get the information I'm looking for. When I run the code from the application I'm writing I get an invalid class error that gets thrown from the foreach loop.
The code I wrote and WMI generated is essentially the same, only the output is different. What could I possibly be doing wrong. Here is the code I wrote.
public List<diskData> getDiskInfo()
{
List<diskData> dData = new List<diskData>();
diskData mydisk = null;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM W32_LogicalDisk");
foreach (ManagementObject item in searcher.Get())
{
mydisk.name = Convert.ToString(item["Name"]);
}
return dData;
}
catch (Exception ex)
{
Console.WriteLine("This is the Message: " + ex.Message);
return dData;
}
}
Thanks for any help you guys can provide.
Paul
The Win32_LogicalDisk class name in your WMI query is misspelled as W32_LogicalDisk.
Related
So i've used this code to get S.M.A.R.T. hard drive diagnostics info from Windows WMI:
http://vasters.com/archive/Reading-ATAPI-SMART-Data-From-Drives-Using-NET-Temperature-Anyone.html
It works on most computers and doesn't on others. After a little bit research and sample testing i found out that it doesn't work on computers whose Hard drives are connected with PCI Express instead of SATA.
var searcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData");
foreach (ManagementObject queryObj in searcher.Get())
{
//do stuff
}
This is where i get exception:
System.Management.ManagementException: 'Not supported'
Is there any other way to do this, or add something in this code to make it work?
I searched this code everywhere and couldn't find working for me, but finaly found on another forum so it's really simple in usage.
Just from my example another way to get WMI info. More Attributes of WMI Win32_DiskDrive you can find in Microsoft DOCs
https://github.com/Mityugin/greentest
string NamespacePath = "\\\\.\\ROOT\\cimv2";
string ClassName = "Win32_DiskDrive";
oClass = new ManagementClass(NamespacePath + ":" + ClassName);
foreach (ManagementObject oObject in oClass.GetInstances())
{
var sign = Convert.ToString(oObject["Signature"]);
var model = Convert.ToString(oObject["Model"]);
var status = Convert.ToString(oObject["Status"]);
if (Equals(sign,""))
{
TextBox1.AppendText("DISK model: " + model);
TextBox1.AppendText(Environment.NewLine);
TextBox1.AppendText("Status: " + status);
TextBox1.AppendText(Environment.NewLine);
if (!status.Equals("OK") || !model.Contains("SSD"))
{
//Here is info if Disk is not OK or model not SSD
}
}
}
This github solution is fine for detecting an SSD but will not tell you it is PCIE or NVMe. I have an SSD that is an older Samsung 960 series and it is an SSD connected via SATA.
The code you need to read an NVMe drive Temperature is on this website at How do I enumerate NVMe (M2) drives an get their temperature in c#?
I hace a WPF application and I'm am using the following to obtain the OS details of my PC:
using (ManagementObjectSearcher win32OperatingSystem = new ManagementObjectSearcher("select * from Win32_OperatingSystem"))
{
foreach (ManagementObject obj in win32OperatingSystem.Get())
{
_operatingSystem = obj["Caption"].ToString();
_osArchitecture = obj["OSArchitecture"].ToString();
break;
}
}
WhenI step into this line:
ManagementObject obj in win32OperatingSystem.Get())
I get the following exception:
Invalid Query.
WHat is wrong here??
WMI classes have a namespace, you didn't specify one. Use WMI Code Creator to get your queries correct, it generates the C# code for you and you can run it right from the tool to check the results.
I would suggest using the properties of the Environment and OperatingSystem class (instead of ManagementObjectSearcher) to get those details.
string _operatingSystem = Environment.OSVersion.VersionString;
Is there a .NET (C#) method or API call that I can use to query if a Windows Service is disabled? The relevant MSDN article is here.
I want to avoid querying the registry directly. Below is some of the code that I am using right now (and it works). However I am looking for something more elegant and less invasive.
const String basepathStr = #"System\CurrentControlSet\services\";
String subKeyStr = basepathStr + servicenameStr;
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(subKeyStr))
{
return (int) key.GetValue("Start");
}
I did find a simliar question but I was hoping for a better answer since the answers are presumably outdated (3 years have passed).
This the most relevant section of the code I decided to use...thanks for the help all!
StartupState state = StartupState.Unknown;
try
{
PermissionSet fullTrust = new PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
fullTrust.Demand();
string wmiQuery = #"SELECT * FROM Win32_Service WHERE Name='" + servicenameStr + #"'";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery);
ManagementObjectCollection results = searcher.Get();
foreach (ManagementObject service in results)
{
if (service["StartMode"].ToString() == "Disabled")
state = StartupState.Disabled;
else
state = StartupState.Enabled;
}
return state;
}
catch (SecurityException se)
{
return StartupState.Refused;
}
catch (Exception e)
{
return StartupState.Error;
}
Use the ServiceController class to get information about services.
EDIT
Seems one of the things you can't do with the ServiceController is get the startup type. Googling showed the following blog post that has code that uses P/Invoke to get the service startup type: http://peterkellyonline.blogspot.de/2011/04/configuring-windows-service.html
Add a ref to System.Management and the following code will get you the StartMode
string wmiQuery = "SELECT * FROM Win32_Service WHERE Name='YourServiceName'";
var searcher = new ManagementObjectSearcher(wmiQuery);
var results = searcher.Get();
foreach (ManagementObject service in results)
{
Console.WriteLine(service["StartMode"]);
}
ServiceController class doesn't provide this information. You should use WMI. See here for detailed solution
WMI can be another way for querying the status of the windows services
You can use:
using System.ServiceProcess;
And then link the service you want to view the satus by:
// Link by service name
ServiceController TheServiceName = new ServiceController();
TheServiceName.ServiceName = "Spooler";
// Link by display name
ServiceController TheDisplayName = new ServiceController();
TheDisplayName.ServiceName = "Print Spooler";
To check for example the isRunning Status :
if (TheServiceName.Status == ServiceControllerStatus.Running)
MessageBox.Show("The service is running.");
Some of our customers inform us that in some cases following error appears:
System.Management.ManagementException: Błąd dostawcy.
at
System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus
errorCode)
at
System.Management.ManagementObjectCollection.ManagementObjectEnumerator.MoveNext()
The error is generated while trying to loop through a colection returned by Get() method of the System.Mamangment.ManagementObjectSearcher object.
This is the code of my method:
private bool PrinterExists(string printerName)
{
bool retVal = false;
SelectQuery q = new SelectQuery("select caption from win32_printer");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(q))
{
foreach (ManagementObject printer in searcher.Get())
{
if(printer["Caption"].ToString() == printerName)
{
retVal = true;
break;
}
}
}
return retVal;
}
It seems that the problem appears only on Windows XP. The only workaround I know is reconstruction of WMI database. It sometimes helps, but unfortunatelly not always.
Can anyone tell me what is the reason of this error and how can I fix it?
There a many possible reasons you could get an error while enumerating a WMI collection, including that you don't have permissions to look at some properties of an object. You can check the permissions possibility by running the app as administrator and seeing if the error goes away.
Regardless of the underlying root cause, one solution you could try is to modify your WQL query to include the name of the printer you're looking for. By having WMI do the enumeration instead of you, it might bypass the problematic items.
SelectQuery q = new SelectQuery(
"select caption from win32_printer where Caption='Fax' ");
bool found = new System.Management.ManagementObjectSearcher(q).Get().Count > 0;
If that doesn't work, then put your comparison of Caption into an exception handler, and ignore printers that throw exceptions.
Of course, if the underlying problem is that you're trying to find printers that you don't have permissions to look at, then you'll need to adjust your application so that it's running with elevated permissions.
When I use this function in c#, it is able to get drive letter but, when I remove the USB stick and test this function, it doesnt go to the Exception.
So could someone help me with where I am going wrong in the function code?
public void GetDriveLetter()
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive where InterfaceType='USB'");
foreach (ManagementObject queryObj in searcher.Get())
{
foreach (ManagementObject b in queryObj.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementBaseObject c in b.GetRelated("Win32_LogicalDisk"))
{
// writer.WriteLine("{0}" + "\\", c["Name"].ToString()); // here it will print drive letter
usbDriveLetter = String.Format("{0}" + "\\", c["Name"].ToString());
}
}
}
}
catch (ManagementException e)
{
MessageBox.Show(e.StackTrace);
}
//CombinedPath = System.IO.Path.Combine(usbDriveLetter.Trim(), path2.Trim());
}
You Method wont throw an Exception as nothing is breaking. If you want to throw and Exception when no usb's are found then you can do this.
if (searcher.Get().Count == 0)
throw new ApplicationException("No Usb drives connected");
Update: will return true if any USB device is found
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive where InterfaceType='USB'");
return (from ManagementObject queryObj in searcher.Get()
from ManagementObject b in queryObj.GetRelated("Win32_DiskPartition")
select b).Select(b => b.GetRelated("Win32_LogicalDisk").Count > 0).FirstOrDefault();
Probably it does not go to the exception because as you have removed the USB stick, the device is not even listed and no exception happens.
Why do you want to generate an exception at all in case the usb stick is not plugged in?
also, you could eventually have better luck replacing the specific exception in the catch definition with a simple Exception object but I don't think this is the issue, as I said above probably no exception is thrown simply because you don^t list anymore the removed device.