How to get faster result of ManagementObject - c#

I'm created method for collecting installed applications version info from windows OS. But facing slowness issue, when assign the value into foreach. Getting ManagementObjectSearcher result is faster. Any suggestion for my requirement?
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Product WHERE Name=Google Chrome");
foreach (ManagementObject obj in searcher.Get()) // this part is taking too long time to process
{
MessageBox.Show(obj["Name"] + "-----" + obj["Version"]);
};

Related

Iterating through list selected from ManagementObjectCollection slow

I am trying to help with a slow legacy application that gets certain data through the ManagementObjectCollection class. This function takes around 40 seconds, however it took a little over a minute when getting the data directly from the ManagementObjectCollection. We pared down the query and selected the data into a list which helped execution time, however it is still very slow considering how many elements are supposed to be here. I have the following code:
string baseStr;
ManagementObjectCollection moReturn;
ManagementObjectSearcher moSearch;
ManagementObjectSearcher moSearch32;
List<string> programs = new List<string>();
List<ProgramDescription> moList;
moSearch32 = new ManagementObjectSearcher("Select Name, Version, InstallDate from Win32_Product");
moReturn = moSearch32.Get();
moList = moReturn.Cast<ManagementObject>().AsEnumerable()
.Select(x => new ProgramDescription
{
Name = x["Name"],
Version = x["Version"],
InstallDate = x["installDate"]
}).ToList();
foreach (ProgramDescription currentMo in moList)
{
if (currentMo.Name == null)
continue;
else
{
baseStr = currentMo.Name.ToString() + ", " + currentMo.Version?.ToString()
+ ", " + currentMo.InstallDate?.ToString();
}
}
As you can see, I am attempting to convert this to a list of another object and iterate through that. However, I have noticed that even when doing this, the foreach loop takes an eternity despite the moList object only having ~290 items. The management object search and converting it to a list seem to happen instantly, but this iteration is still taking forever. Why is this? If this is just a quirk in relation to accessing these management objects, is there a more efficient way of getting this specific query?

Fastest way of getting properties of ManagementObject

I have a method that returns list of services on remote machine. I'm getting the ManagementObjectCollection using ManagementObjectSearcher.Get() and WIN32 query. Then in foreach loop I'm creating instance of my Service class and add it to result List. While initializing new Service I'm getting ManagementObject properties using GetPropertyValue(string). The problem i'm facing is that this process is very slow. I think that GetPropertyValue is slow(I'm using it 7 times per loop). Is there faster way of getting properties from ManagementObject class?
var query = new ObjectQuery("Select Name, DisplayName, ProcessId, Description, State, StartMode, StartName From Win32_Service");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection allServices = searcher.Get();
foreach (ManagementObject p in allServices)
{Service newService = new Service{ Name = p.GetPropertyValue("Name"),etc...} result.Add(newService);}
I have been fighting with this, trying to understand what is so slow.
I wrote a test program, and used Stopwatch to time practically everything.
I have a wql query that returns 3 devices from Win32_PnPSignedDriver.
I used three different methods to retrieve the results from the query.
ManagementObjectCollection queryResults;
ManagementObjectSearcher searcher = new ManagementObjectSearcher();
var myWql = "SELECT * FROM Win32_PnPSignedDriver WHERE ..."
searcher.Scope = new ManagementScope(#"root\CIMV2");
searcher.Query = new WqlObjectQuery(wmiQry);
queryResults = searcher.Get();
searcher.Get() is plenty fast.
I tested three methods of retrieving data from ManagementObjectCollection queryResults.
foreach (ManagementBaseObject device in queryResults) { }
IEnumerator enumerator = queryResults.GetEnumerator(); while (enumerator.MoveNext()) { }
queryResults.CopyTo(deviceArray, 0); foreach (var btDevice in deviceArray)
First round testing:
Method 1: Was very slow -- over 3000 ms to execute an empty loop.
Method 2: Was very fast. 1 ms
Method 3: Also very fast. 0 ms.
Then I saw the fault in my testing. The first loop counted the object in the collection, and then this was remembered by the framework. If I executed Method 1 several times, only the initial loop was slow, but then repeating the foreach was 0 to 1 ms.
I restructured my test to re-execute the query before each fetch of the data.
Method 1: Was slow every time.
Method 2: Also slow every time.
Method 3: My Stopwatch timing reported 0 to 1 ms, but I noticed the execution time was much longer. ???
Looking deeply into what I coded, I saw that I did not time the following line:
ManagementObject[] deviceArray = new ManagementObject[queryResults.Count];
Which is actually two commands:
var count = queryResults.Count;
ManagementObject[] deviceArray = new ManagementObject[count];
I timed each separately, and saw that the queryResults.Count took almost all the time. Often > 3000 ms.
I then hard-coded the size of the array to avoid the call: queryResults.Count
However, when I executed
queryResults.CopyTo(deviceArray, 0);
The CopyTo method still needed to know how many items are in the ManagementObjectCollection, and now the CopyTo took > 3000 ms where it had been 0 or 1 ms before.
So, it would appear that ManagementObjectCollection. get_Count is the bottleneck, and I do not know anyway to retrieve the results without causing the Count getter to be executed.

C# Using WMI To Query LogicalDisk Information

I'm looking to get performance information for the disks on my local computer using WMI. According to the documentation for Win32_PerfFormattedData_PerfDisk_LogicalDisk (http://msdn.microsoft.com/en-us/library/aa394261(v=vs.85).aspx), it looks like I should just be able to query the information and get the values.
However, when I run the code I get "0" for each value for the properties.
var selectQuery = new SelectQuery("Select * from Win32_PerfFormattedData_PerfDisk_LogicalDisk");
var searcher = new ManagementObjectSearcher(selectQuery);
foreach (ManagementObject disk in searcher.Get())
{
foreach (PropertyData property in disk.Properties)
{
var propertyValue = property.Value; // 0 value.
}
}
I have also queried Win32_PerfRawData_PerfDisk_LogicalDisk and I do get actual raw values. Of course, I would rather have the formatted data instead of the raw data. The documentation for converting the raw data to the formatted data seems to be lacking when it comes to using WMI.
Any idea why I am getting 0 for each value?
Here is a working example just tested this
You can use the WMI Performance Class Counters. An example of this would be polling the PerfDisk_LogicalDisk
ManagementObjectSearcher mos = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfDisk_LogicalDisk");
foreach (ManagementObject service in mos.Get())
{
foreach (PropertyData propData in service.Properties)
{
Console.WriteLine("{0} {1}", propData.Name, propData.Value);
}
}

How can I get motherboard and CPU Voltage informations in C#?

As far as I research on internet, I tried some codes but it's working. it returned '0' value. My question is:How can I get motherboard and CPU Voltage informations in C#?
My code:
//http://wutils.com/wmi/
//create a management scope object
ManagementScope scope = new ManagementScope("\\\\.\\ROOT\\cimv2");
//create object query
ObjectQuery query = new ObjectQuery("SELECT * FROM CIM_VoltageSensor");
//create object searcher
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(scope, query);
//get collection of WMI objects
ManagementObjectCollection queryCollection = searcher.Get();
//enumerate the collection.
foreach (ManagementObject m in queryCollection)
{
// access properties of the WMI object
Console.WriteLine("Accuracy : {0}", m["Accuracy"]);
}
Look at the OpenHardwareMonitor opensource project.
You may find this helpful. The explanation of the examples are here.
Look into frmMain.cs example.

Using ManagementObject to retrieve a single WMI property

This probably isn't the best way, but I am currently retrieving the amount of RAM on a machine using:
manageObjSearch.Query = new ObjectQuery("SELECT TotalVisibleMemorySize FROM Win32_OperatingSystem");
manageObjCol = manageObjSearch.Get();
foreach (ManagementObject mo in manageObjCol)
sizeInKilobytes = Convert.ToInt64(mo["TotalVisibleMemorySize"]);
It works well and good, but I feel I could be doing this more directly and without a foreach over a single element, but I can't figure out how to index a ManagementObjectCollection
I want to do something like this:
ManagementObject mo = new ManagementObject("Win32_OperatingSystem.TotalVisibleMemorySize")
mo.Get();
Console.WriteLine(mo["TotalVisibleMemorySize"].ToString())
or maybe even something like
ManagementClass mc = new ManagementClass("Win32_OperatingSystem");
Console.WriteLine(mc.GetPropertyValue("TotalVisibleMemorySize").ToString());
I just can't seem to figure it out. Any ideas?
The foreach statement is hiding the enumerator you need to access. You can do it directly like this:
var enu = manageObjSearch.Get().GetEnumerator();
if (!enu.MoveNext()) throw new Exception("Unexpected WMI query failure");
long sizeInKilobytes = Convert.ToInt64(enu.Current["TotalVisibleMemorySize"]);

Categories

Resources