WMI call to get drivers - c#

I am new using WMI. What is it?
Can I use WMI call in C# for example to get list of drivers on my PC? If so, which class do I call?

To list the installed drivers you can use the Win32_PnPSignedDriver WMI class as is show on this sample.
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
static void Main(string[] args)
{
try
{
string ComputerName = "localhost";
ManagementScope Scope;
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_PnPSignedDriver");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
Console.WriteLine("{0,-35} {1,-40}","ClassGuid",WmiObject["ClassGuid"]);// String
Console.WriteLine("{0,-35} {1,-40}","DeviceClass",WmiObject["DeviceClass"]);// String
Console.WriteLine("{0,-35} {1,-40}","DeviceID",WmiObject["DeviceID"]);// String
Console.WriteLine("{0,-35} {1,-40}","DeviceName",WmiObject["DeviceName"]);// String
Console.WriteLine("{0,-35} {1,-40}","Manufacturer",WmiObject["Manufacturer"]);// String
Console.WriteLine("{0,-35} {1,-40}","Name",WmiObject["Name"]);// String
Console.WriteLine("{0,-35} {1,-40}","Status",WmiObject["Status"]);// String
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}
Also if you are new in the WMI topic you can use a tool like the WMI Delphi Code Creator to explore the WMI contents and generate code to access the WMI.

Related

WMI classes reference

I have the following problem:
I want to get the the logged in user with a WMI class.
So I tried this:
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROMWin32_LoggedOnUser");
foreach (ManagementObject queryObj in searcher.Get())
{
accounttype += queryObj["Antecedent"];
}
}
catch
{
accounttype = "error";
}
But this don't work because the queryObj returns a reference to Win32_Account!
I have no Idea how I can read the values of this Win32_Account reference!
BTW,
I know there are other ways ( like Environment.UserName, but I want to generally understand these reverences!
Thanks!
The Antecedent and Dependent properties of the Win32_LoggedOnUser WMI class returns a WMI Object Path, which is a unique id for a WMI class instance, you can access the data of to this class creating a instance to the ManagementObject object and then setting the property Path obtained from a ManagementPath object.
Try this sample
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", "localhost"), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_LoggedOnUser");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
//Console.WriteLine("{0,-35} {1,-40}","Antecedent",WmiObject["Antecedent"]);// Reference
//Console.WriteLine("{0,-35} {1,-40}","Dependent",WmiObject["Dependent"]);// Reference
ManagementObject oAntecedent = new ManagementObject();
ManagementPath ObjectPath = new ManagementPath((String)WmiObject["Antecedent"]);//Win32_Account
oAntecedent.Path = ObjectPath;
oAntecedent.Get();
Console.WriteLine("{0,-35} {1,-40}", "Caption", oAntecedent["Caption"]);// String
Console.WriteLine("{0,-35} {1,-40}", "Description", oAntecedent["Description"]);// String
Console.WriteLine("{0,-35} {1,-40}", "Domain", oAntecedent["Domain"]);// String
//Console.WriteLine("{0,-35} {1,-40}", "InstallDate", ManagementDateTimeConverter.ToDateTime((string)WmiObject["InstallDate"]));// Datetime
Console.WriteLine("{0,-35} {1,-40}", "LocalAccount", oAntecedent["LocalAccount"]);// Boolean
Console.WriteLine("{0,-35} {1,-40}", "Name", oAntecedent["Name"]);// String
Console.WriteLine("{0,-35} {1,-40}", "SID", oAntecedent["SID"]);// String
Console.WriteLine("{0,-35} {1,-40}", "SIDType", oAntecedent["SIDType"]);// Uint8
Console.WriteLine("{0,-35} {1,-40}", "Status", oAntecedent["Status"]);// String
Console.WriteLine();
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}

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

Is a process running on a remote machine?

I have three remote PC's to which I remotely connect. I am trying to write a simple Windows application that would display in a single window whether a particular process is running on either of the machines, e.g.
Server1: Chrome not running
Server2: Chrome IS running
Server3: Chrome IS running
I used WMI and C#. So far I've got this much:
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Username = #"domain\username";
connectoptions.Password = "password";
//IP Address of the remote machine
string ipAddress = "192.168.0.217";
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + #"\root\cimv2");
scope.Options = connectoptions;
//Define the WMI query to be executed on the remote machine
SelectQuery query = new SelectQuery("select * from Win32_Process");
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query))
{
ManagementObjectCollection collection = searcher.Get();
foreach (ManagementObject process in collection)
{
// dwarfs stole the code!! :'(
}
}
I think it is all set up correctly, but if I MessageBox.Show(process.ToString()) inside the foreach loop, I get a whole bunch of message boxes with the following text:
\\username\root\cimv2:W32_Process.Handle="XXX"
I am kind of stuck. Is there any way I can "translate" that XXX to a process name? Or else, how can actually get the names of the processes so I can use an if statement to check whether it is a "chrome" process?
Or...is my implementation an overkill? Is there an easier way to accomplish this?
Thanks a lot!
In your foreach, try this:
Console.WriteLine(process["Name"]);
You can filter the name of the process to watch in the WQL sentence, so you can write something like this
SelectQuery query = new SelectQuery("select * from Win32_Process Where Name='Chrome.exe'");
Try this sample app
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
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 * FROM Win32_Process Where Name='Chrome.exe'");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
//for each instance found, do something
Console.WriteLine("{0,-35} {1,-40}","Name",WmiObject["Name"]);
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}
Try Process.GetProcesses("chrome", "computerName");
Defined in System.Diagnostics.Process as
public static Process[] GetProcessesByName(
string processName,
string machineName)

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

Accessing the number of processors in WMI

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

Categories