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#?
Related
My C# application sits on the embedded box which has Intel motherboard and graphics chipset. ATI graphics card is put on to PCI express. Generally graphics card drives the video, but if ATI card fails then the video comes out from graphics chipset.
I have to detect the failure of ATI graphics card for diagnostic purposes.
Any ideas/sample code on how to do this.
Thanks in advance
Raju
This should hopefully get you started.
Add a reference to System.Management, then you can do this:
ManagementObjectSearcher searcher
= new ManagementObjectSearcher("SELECT * FROM Win32_DisplayConfiguration");
string graphicsCard = string.Empty;
foreach (ManagementObject mo in searcher.Get())
{
foreach (PropertyData property in mo.Properties)
{
if (property.Name == "Description")
{
graphicsCard = property.Value.ToString();
}
}
}
In my case, graphicsCard is equal to
NVIDIA GeForce 8400 GS (Microsoft
Corporation - WDDM v1.1)
I'm not a fan of how the selected answer only returns the first video controller. Also, there's no need to loop over all the properties. Just get the ones you need. If CurrentBitsPerPixel is not null, then you're looking at one of the active controllers. I'm using Win32_VideoController as suggested by #bairog, instead of the deprecated Win32_DisplayConfiguration.
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_VideoController");
foreach (ManagementObject mo in searcher.Get())
{
PropertyData currentBitsPerPixel = mo.Properties["CurrentBitsPerPixel"];
PropertyData description = mo.Properties["Description"];
if (currentBitsPerPixel != null && description != null)
{
if (currentBitsPerPixel.Value != null)
System.Console.WriteLine(description.Value);
}
}
My machine has 3 video controllers. The first one is not active (ShoreTel). The second one is active, but is not the video card (Desktop Authority). The third one is my NVidia. This code will print out both the DA controller and the NVidia controller.
Promoted answer works only for single video card system. When I have ATI and Nvidia cards - WMI query returns ATI even if that monitor is plugged into Nvidia card, dxdiag shows Nvidia and games runs on that card (usage).
The only way I could determine right video card was using SlimDX to create DX device and examine what card it used. However that .dll weights over 3Mb.
var graphicsCardName = new Direct3D().Adapters[0].Details.Description;
Your question isn't entirely clear, so I'm not sure if the follwing idea will help or not.
Perhaps something very simple would suffice:
If the two graphics cards run different resolutions check the monitor resolution using:
System.Windows.Forms.SystemInformation.PrimaryMonitorSize
Similarly, if one card supports more than one monitor, check the number of monitors using SystemInformation.MonitorCount.
I tried all the approaches in this question but none gives me a correct answer. However I found it possible to get your current using the Win32_DisplayControllerConfiguration class. Although according to MSDN this class is obsolete, it's the only one returning a correct answer:
using System;
using System.Management;
using System.Windows.Forms;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DisplayControllerConfiguration");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("----------------------------------- ");
Console.WriteLine("Win32_DisplayControllerConfiguration instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Name: {0}", queryObj["Name"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
}
}
(Code generated by WMI Code Creator, a great tool if you are messing with WMI.)
This gives GeForce GTX 1080 on my Windows 10 (RS2) + Intel(R) HD Graphics 4600 + NVIDIA GeForce GTX 1080 system.
Sometimes I need to switch between the Nvidia GPU and onboard GPU. To know which is connected to the monitor, I use the property MinRefreshRate. It works reliably for me, not CurrentBitsPerPixel.
public static void UpdateActiveGpu()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_VideoController");
foreach (ManagementObject mo in searcher.Get())
{
PropertyData minRefreshRate = mo.Properties["MinRefreshRate"];
PropertyData description = mo.Properties["Description"];
if (minRefreshRate != null && description != null && minRefreshRate.Value != null)
{
Global.Instance.activeGpu = description.Value.ToString();
break;
}
}
}
How can I dismount a logical drive temporarily on my computer in c#? I am looking for a code that gives me similar results
Dismount/Hide Drives
//Do some work
Mount / Show Drives
I had tried this code to renaming the drive letters, but cannot understand how to use the Dismount method
ManagementObjectSearcher searchDrives = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Volume WHERE label = 'Data'");
foreach (ManagementObject Drive in searchDrives.Get())
{
Drive.Get();
Drive["DriveLetter"] = "M:";
Drive.Put();
}
This is the Method provided by WMI
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/vdswmi/dismount-method-in-class-win32-volume
How should I use it, please?
I want to get all a list of all installed drivers on my machine. For this purpose I use WMI. But for unknown reason all properties returned have empty values (except for deviceID, DriverVersion and Signer) .
What I tried and considered so far:
running with and without admin rights makes no difference
no methods found like fetch, load, reload on any of involved objects found
no option found like lazyload
pnputil.exe and driversearch.exe do return data of all drivers, but the outputs of those a very hard to interpret
This is the C#-code:
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPSignedDriver"))
{
foreach (ManagementBaseObject u in searcher.Get())
{
foreach(PropertyData prop in u.Properties)
{
System.Console.WriteLine($"{prop.Name}={prop.Value}");
}
System.Console.WriteLine("===");
}
}
Output for first driver found:
Caption=
ClassGuid=
CompatID=
CreationClassName=
Description=
DeviceClass=
DeviceID=\\SVWPSW46\P3115 X WC 7120-D C S U A3
DeviceName=
DevLoader=
DriverDate=
DriverName=
DriverProviderName=
DriverVersion=2:6.0,2:5.2,2:5.1,2:5.0
FriendlyName=
HardWareID=
InfName=
InstallDate=
IsSigned=True
Location=
Manufacturer=
Name=
PDO=
Signer=Microsoft Windows
Started=
StartMode=
Status=
SystemCreationClassName=
SystemName=
===
...
In part of a program I am writing, I'm trying to pull device information about specified local hard drives. I've been able to create a few value returning methods using the DriveInfo class like this:
//Gets drive format
public string GetDriveFormat(string driveName)
{
foreach (DriveInfo drive in DriveInfo.GetDrives())
{
if (drive.IsReady && drive.Name == driveName)
{
return drive.DriveFormat;
}
}
return "";
}
//Example of use
MessageBox.Show(GetDriveFormat("C:\\"));
The problem I'm running into now is that there doesn't seem to be a Model property to the DriveInfo class. I've looked all over but am unable to find a way to construct a value returning method that will return the model of a drive like what is viewable in device manager.
Any help would be greatly appreciated,
Thanks!
Unfortunately, you cannot get the Drive's Manufacturer and Model using the DriveInfo class.
You'll have to resort back to WMI:
WqlObjectQuery q = new WqlObjectQuery("SELECT * FROM Win32_DiskDrive");
using (ManagementObjectSearcher res = new ManagementObjectSearcher(q)) {
foreach (ManagementObject o in res.Get()) {
Console.WriteLine("Caption = " + o["Caption"]);
Console.WriteLine("DeviceID = " + o["DeviceID"]);
Console.WriteLine("Decsription = " + o["Description"]);
Console.WriteLine("Manufacturer = " + o["Manufacturer"]);
Console.WriteLine("MediaType = " + o["MediaType"]);
Console.WriteLine("Model = " + o["Model"]);
Console.WriteLine("Name = " + o["Name"]);
// only in Vista, 2008 & etc: //Console.WriteLine("SerialNumber = " + o["SerialNumber"]);
} }
Not sure if you need to consider mounted drives as well:
foreach(ManagementObject volume in new ManagementObjectSearcher("Select * from Win32_Volume" ).Get())
{
...
}
You'll need to use a lower-level API to get this information, and even then it still might not be accurate.* The internal details of the hard drives is exposed in the Win32 APIs, which you can still access in C# through WMI.
*: Note that this is still limited to the hardware information as Windows is able to see it. In some conditions, it won't or can't be accurate (e.g. with a RAID array, where Windows sees N drives as a single drive).
I'm not entirely sure if you can get that info without using lower level api's. This post should help you achieve your goal.
http://www.codeproject.com/Articles/17973/How-To-Get-Hardware-Information-CPU-ID-MainBoard-I
Quick summary of the link:
Add a reference to the System.Management library
Then you can use:
var disks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject disk in disks.Get())
{
Console.WriteLine(disk["Model"].ToString());
Console.WriteLine("\tSerial: " + disk["SerialNumber"]);
}
here is something that can also work for you feel free to tweak it as you please
String drive = "c";
ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + ":\"");
disk.Get();
Console.WriteLine(disk["VolumeName"]);
foreach (var props in disk.Properties)
{
Console.WriteLine(props.Name + " " + props.Value);
}
Console.ReadLine();
I want to be able to do the equivalent of the following in c#:
Go into "Devices and Printers"
Right click a printer
Go to the ports tab
Select COM12: port
click OK
I have managed to get a ManagementObject for a named printer and tried to call:
mObj.SetPropertyValue("PortName","COM12:");
On the ManagementObject for that Printer - whch inherits from ManagementBaseObject.
However, this piece of code didn't do anything to the Printer Settings.
I suspect that I will need to use P/Invoke on the appropriate library but after a lot of searching I cannot find the library or a tutorial for how to do this from c#.
Any help would be much appreciated.
Found the answer on an obscure part of the internet:
public static void SetPrinterPort(string printerName, string portName)
{
var oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
oManagementScope.Connect();
SelectQuery oSelectQuery = new SelectQuery();
oSelectQuery.QueryString = #"SELECT * FROM Win32_Printer
WHERE Name = '" + printerName.Replace("\\", "\\\\") + "'";
ManagementObjectSearcher oObjectSearcher =
new ManagementObjectSearcher(oManagementScope, #oSelectQuery);
ManagementObjectCollection oObjectCollection = oObjectSearcher.Get();
foreach (ManagementObject oItem in oObjectCollection)
{
oItem.Properties["PortName"].Value = portName;
oItem.Put();
}
}
I am pretty sure that the last part is all you need to set properties on any Management Object. It was driving me nuts that I could see that the Win32 API said the property I wanted to set was read/write but nowhere seemed to have the code for setting it.
Well now we know! :-)
I hope this is useful for someone.