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;
}
}
}
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'm trying to get the total VRAM of a system using WMI calls, I'm testing in my dev machine which has a NVIDIA GTX 1080 8GB GPU but the property AdapterRAM from Win32_VideoController says that my card only has 4 GB of VRAM. Not sure if there's any issue with the property or my code.
Here's the code I'm using
private void GetVideoInfo()
{
foreach (var mgmtObj in GetManagementClassProperties("Win32_VideoController"))
{
VideoInfoLabel.Content = ToUInt64(mgmtObj["AdapterRAM"]) / 1073741824;
}
}
public ManagementObjectCollection GetManagementClassProperties(string id)
{
return new ManagementClass(id).GetInstances();
}
Thanks!
I am developing an application with C# winforms.
Our application is going to be installed on win8 surface(touch screen device).
We want to check if a keyboard is connected via USB then our app will not show soft keypad otherwise it will show.
Many methods are avaliable to check for WinRT but none for winforms C#.
Please let me know if my question is not clear.
Thanks in advance.
I just wrote this and tested on W8:
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select Name from Win32_Keyboard");
foreach(ManagementObject keyboard in searcher.Get())
{
if (!keyboard.GetPropertyValue("Name").Equals(""))
{
Console.WriteLine("KB Name: {0}", keyboard.GetPropertyValue("Name"));
}
}
I also connected a second keyboard and can see it detected. When I unplug one I get one entry, when unplug both I get nothing.
I also found some examples here:
Example 1
and here Example 2
Hope this helps.
To determine if it is connected via USB, check for that string:
private readonly string USB = "USB";
private bool GetKeyboardPresent()
{
bool keyboardPresent = false;
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * from Win32_Keyboard");
foreach (ManagementObject keyboard in searcher.Get())
{
foreach (PropertyData prop in keyboard.Properties)
{
if (Convert.ToString(prop.Value).Contains(USB))
{
keyboardPresent = true;
break;
}
}
}
return keyboardPresent;
}
Or you could instead potentially use this Powershell command:
PS C:\Users\myUserID> Get-WmiObject Win32_Keyboard
I know we can get the BIOS information using system.management assembly but the assembly is not accessible for windows 8 app. I specifically need to know the serial number of the laptop on which the app is running. Is there any way that I can access that ?
I don't think there is a way if you are developing a Windows Modern UI App.
Modern UI Apps get run in a sandbox environment which have very limited access to anything. Check MSDN documentations on that.
If you are developing a desktop Windows app on the other hand, then try the following code:
(You need to import System.Management.dll into your project.)
using System;
using System.IO;
using System.Management;
namespace GetHardwareIds
{
internal class Program
{
private static void Main(string[] args)
{
using (StreamWriter writer = new StreamWriter(#"C:\HardwareInfo.txt"))
{
using
(
ManagementObjectSearcher searcher =
// Where __Superclass Is Null: selects only top-level classes.
// remove it if you need a list of all classes
// new ManagementObjectSearcher("Select * From meta_class Where __Superclass Is Null")
// this query only select the processor info. for more options uncomment top line
new ManagementObjectSearcher("Select * From meta_class Where __Class = 'Win32_Processor'")
)
{
foreach (ManagementObject managementObject in searcher.Get())
{
Console.WriteLine(managementObject.Path.ClassName);
writer.WriteLine(managementObject.Path.ClassName);
GetManagementClassProperties(managementObject.Path.ClassName, writer);
managementObject.Dispose();
}
}
}
}
public static void GetManagementClassProperties(string path, StreamWriter writer)
{
using (ManagementClass managementClass = new ManagementClass(path))
{
foreach (ManagementObject instance in managementClass.GetInstances())
{
foreach (PropertyData property in instance.Properties)
{
Console.WriteLine(" {0} = {1}", property.Name, property.Value);
writer.WriteLine(" {0} = {1}", property.Name, property.Value);
}
instance.Dispose();
}
}
}
}
}
Check this code. I am not a 100% clear on what you are trying to achieve but this code should return the device ID specified by Win8 (this code includes a concatenation of all ids.)
// get hardware token
HardwareToken token = HardwareIdentification.GetPackageSpecificToken(null);
// get hardware ID bytes
byte[] idBytes = hwToken.Id.ToArray();
// populate device ID as a string value
string deviceID = string.Join(",", idBytes);
Here is the link to MSDN articles about it:
http://msdn.microsoft.com/en-us/library/windows/apps/jj553431.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.profile.hardwareidentification.getpackagespecifictoken.aspxThere is an entry for BIOS in the return structure based on these articles.
Hopefully, this does what you need. Let me know if it worked :)
Unfortunately the information you want to obtain is not available to WinRT applications.
I am using NAudio to play an mp3 file in my WinForms app. However, the file needs to be played to user-selected device, not the windows default one. So, what I am doing now is loading all available devices using this code:
{
ManagementObjectSearcher mo =
new ManagementObjectSearcher("select * from Win32_SoundDevice");
foreach (ManagementObject soundDevice in mo.Get())
{
String name = soundDevice.GetPropertyValue("Name").ToString();
comboBox1.Items.Add(name);
}
}
Now, NAudio requires some Device ID to change the active device. How do I get this ID, using the input from the comboBox (the device name)?
If you're using NAudio and with WaveOut, you can get the device names like this:
for (int deviceId = 0; deviceId < WaveOut.DeviceCount; deviceId++)
{
var capabilities = WaveOut.GetCapabilities(deviceId);
comboBoxWaveOutDevice.Items.Add(capabilities.ProductName);
}
The one caveat is that the old waveOut APIs don't allow for product names with more than 31 characters so they can appear truncated. If this turns out to be a problem for you, then DirectSoundOut or WasapiOut might be a good alternative.