Accessing the number of processors in WMI - c#

I have looked through a number of posts on here regarding the WMI and am still having a little trouble. I would like to retrive the CPU useage from WMI, my query retrieves everything the ManagementObjectSearcher has to offer, but it returns a null and never pulls any information back.
Also, for the datatype I am pulling should I be using a int16?
Hopefully someone can shed a little light on this and send me on my way. Thanks.
public void GetPhysicalMemory()
{
ManagementObjectSearcher mgtObj = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_ComputerSystem"); // Win32_OPeratingSystem");
ManagementObjectCollection mgtColl = mgtObj.Get();
// foreach (ManagementObject obj in mgtObj.Get())
if (mgtColl.Count != 0 )
{
foreach (ManagementBaseObject mgtBaseObj in mgtColl)
{
var[] data = mgtBaseObj["NumberOfProcessors"] as int16[];
if (data != null)
{
Console.WriteLine(data);
}
else
{
Console.WriteLine("Collection = null");
Console.Read();
Console.Read();
}
}
}

you can can iterate directly over the collection returned by ManagementObjectSearcher.Get method using a ManagementObject variable, from here you can access you can access each property using the item property or through the [] notation.
Check this sample application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
namespace ConsoleFoo
{
class Program
{
static void Main(string[] args)
{
try
{
ManagementObjectSearcher mgtObj = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_ComputerSystem");
foreach (ManagementObject item in mgtObj.Get())
{
Console.WriteLine("Number Of Processors {0}", item["NumberOfProcessors"]);
}
}
catch (ManagementException e)
{
Console.WriteLine("Exception {0} ", e.Message);
}
Console.ReadKey();
}
}
}

Related

Get disk time in percentage in windows

I have the following scenario, I want to get the utilization (Disk Time) per disk in percent.
Unfortunately it always returns the value 0 when I switch through the instances, why?
Here is my code:
while (true)
{
foreach (var disk in DriveInfo.GetDrives())
{
var diskInstances = diskCounterCategory.GetInstanceNames();
var diskInstance = string.Empty;
foreach(var instance in diskInstances)
{
if (instance.Contains(disk.Name[0].ToString()))
{
var tesst = new PerformanceCounter("PhysicalDisk", "% Disk Time", instance);
var tesst3 = (uint)tesst.NextSample().BaseValue;
Console.WriteLine(tesst3);
}
}
}
Thread.Sleep(1000);
}
I had the same issue. Here is the solution I came up with:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main()
{
Console.WriteLine("Setting up the counters...");
Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
Dictionary<string, PerformanceCounter> diskCounters = new Dictionary<string, PerformanceCounter>();
PerformanceCounterCategory logicalDiskCategory = PerformanceCounterCategory.GetCategories().FirstOrDefault(x => x.CategoryName.Equals("LogicalDisk"));
if (logicalDiskCategory == null)
{
Console.WriteLine("ERROR: Category not found!");
return;
}
string[] diskInstances = logicalDiskCategory.GetInstanceNames();
foreach (string diskName in diskInstances)
{
PerformanceCounter counter = logicalDiskCategory.GetCounters(diskName).FirstOrDefault(x => x.CounterName.Equals("% Disk Time"));
if (counter != null)
{
diskCounters.Add(diskName, counter);
}
}
while (true)
{
Console.Clear();
foreach (KeyValuePair<string, PerformanceCounter> pair in diskCounters)
{
Console.WriteLine($"Time: {DateTime.Now.ToString("HH:mm:ss")}\t| Disk: {pair.Key}\t| Utilisation: {pair.Value.NextValue()}%");
}
Thread.Sleep(1000);
}
}
}
}
Explanation:
When we create a counter on our own, like this:
new PerformanceCounter("LogicalDisk", "% Disk Time", "C:");
it will constantly return 0. I myself don’t know why this is so, but if we take PerformanceCounterCategory from the PerformanceCounterCategory.GetCategories() array and then find the desired counter in it through GetCounters(DiskName), the counter will start to produce non-zero results!
But there is one issue in here. If you try to check the names of the Categories you got from the PerformanceCounterCategory.GetCategories() they will be localized, so it is very important to set the Thread.CurrentThread.CurrentCulture to en-US before accessing it, because in other case it will not work at all or will not work on others computers.
Hope this helped)

How to get HDD serial number

May be the title is duplicate. I am getting HDD of the laptop serial number successfully when no USB devices are connected. But when any USB is connected, the code gets the serial number of connected device. I only want the serial number of HDD of laptop or desktop even though USBs are connected.
Below is the code.
using System.Management;
namespace SystemInfo
{
public class Info1
{
public static String GetHDDSerialNo()
{
ManagementClass mangnmt = new ManagementClass("Win32_LogicalDisk");
ManagementObjectCollection mcol = mangnmt.GetInstances();
string result = "";
foreach (ManagementObject strt in mcol)
{
result += Convert.ToString(strt["VolumeSerialNumber"]);
}
return result;
}
}
}
try this
ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
foreach (ManagementObject currentObject in theSearcher.Get())
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}
You can use WMI Win32_DiskDrive, filter on MediaType containing "fixed" and get the SerialNumber
Something like :
public static String GetHDDSerialNo()
{
ManagementClass mangnmt = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection mcol = mangnmt.GetInstances();
string result = "";
foreach (ManagementObject strt in mcol)
{
if (Convert.ToString(strt["MediaType"]).ToUpper().Contains("FIXED"))
{
result += Convert.ToString(strt["SerialNumber"]);
}
}
return result;
}
Media type can contain "External", "Removable", "fixed". Exact string depends on OS. On Seven and XP, that String can be different. That's why we use Contains.
little reading

WMI query returns nothing

I am making a query with WMI to check for a particular drive letter, if it does not exist then I want to run a method that will create it with specific settings. Now the problem I am facing is when I send a test query to see if the drive letter exists, it returns empty. No error or exception.
How would I handle this type of situation?
Thanks
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\cimv2",
#"SELECT * FROM Win32_Volume Where DriveLetter = '" + DriveLetter + "'");
foreach (ManagementObject queryObj in searcher.Get())
{
drives.CurrentDriveLetter = queryObj["DriveLetter"] == null ? "null" : queryObj["DriveLetter"].ToString();
drives.CurrentDriveSize = queryObj["Capacity"] == null ? "null" : queryObj["Capacity"].ToString();
drives.CurrentDriveName = queryObj["Label"] == null ? "null" : queryObj["Label"].ToString();
}
Following your comments you only need determine if the collection returned by the ManagementObjectSearcher.Get method has elements. For that you can use the Count property.
Try this sample code
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
static void Main(string[] args)
{
try
{
ManagementScope Scope;
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", "."), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_Volume Where DriveLetter='X:' ");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
if (Searcher.Get().Count==0)
{
Console.WriteLine("Do something, when the collection is empty.");
}
else
foreach (ManagementObject WmiObject in Searcher.Get())
{
Console.WriteLine("{0} {1}","Name",WmiObject["Name"]);// String
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}

terminating process requires WQL "SELECT *..."?

i'm writing code to terminate specific processes after a specified amount of time. i'm using the below code (simplified for post):
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name, CreationDate FROM Win32_Process WHERE Name = 'foo'");
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
}
the problem -- using a WQL statement of SELECT Name, CreationDate throws an exception when trying to do the terminate:
"Operation is not valid due to the current state of the object."
...but, using SELECT * works and terminates the process. why is this -- is there a specific WMI column that's needed in the resultset?
thanks!
When you executes a WMI method, the WMI internally searh for the WMI Object path to identify the instance over the method will be executed.
In this case for the Win32_Process WMI class the WMI Object Path looks like Win32_Process.Handle="8112", So as you see the Handle property is part of the WMi Object path and must be included in your WQL sentece,
Check this sample.
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
//this will all the notepad running instances
namespace GetWMI_Info
{
class Program
{
static void Main(string[] args)
{
try
{
string ComputerName = "localhost";
ManagementScope Scope;
if (!ComputerName.Equals("localhost", StringComparison.OrdinalIgnoreCase))
{
ConnectionOptions Conn = new ConnectionOptions();
Conn.Username = "";
Conn.Password = "";
Conn.Authority = "ntlmdomain:DOMAIN";
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), Conn);
}
else
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT Handle FROM Win32_Process Where Name='notepad.exe'");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
WmiObject.InvokeMethod("Terminate", null);
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}

USB Device Connected

I'm trying to make a function that detects if a usb device is connected given the devices pid and vid. I'm hoping it would look something like this, I'm just not sure how to do this in C#.
public bool IsUsbDeviceConnected(string pid, string vid)
{
//Code here
}
//using System.Management
public bool IsUsbDeviceConnected(string pid, string vid)
{
using (var searcher =
new ManagementObjectSearcher(#"Select * From Win32_USBControllerDevice"))
{
using (var collection = searcher.Get())
{
foreach (var device in collection)
{
var usbDevice = Convert.ToString(device);
if (usbDevice.Contains(pid) && usbDevice.Contains(vid))
return true;
}
}
}
return false;
}
may be something like
//import the System.Management namespace at the top in your "using" statement. Then in a method, or on a button click:
ManagementObjectCollection collection;
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'"))
collection = searcher.Get();
foreach (ManagementObject currentObject in collection)
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}
collection.Dispose();
Using WMI

Categories