SelectQuery eating up 100% CPU - c#

I am doing a query for all the users on the machine and when it executes it grabs 100% CPU and locks up the system. I have waited up to 5 minutes and nothing happens.
In the Task Manager wmiprvse.exe is using all the CPU. When I kill that process everything returns to normal.
Here is my code:
SelectQuery query = new SelectQuery("Win32_UserAccount",
"LocalAccount=1 and Domain='" + GetMachine().DomainName + "'");
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher(query)) {
IList<WindowsUser> users = new List<WindowsUser>();
Console.WriteLine("Getting users...");
foreach (ManagementObject envVar in searcher.Get()) {
Console.WriteLine("Getting " + envVar["Name"].ToString() + "...");
}
}
In the console all I see is Getting users... and nothing else. The problem appears to be with searcher.Get().
Does anyone know why this query is taking 100% CPU? Thanks.
EDIT: OK I found that it the WMI process is only eating 25% CPU but it doesn't get released if I end the program (the query never finishes). The next time I start an instance the process goes up to 50% CPU, etc, etc until it is at 100%.
So my new question is why is the CPU not getting released and how long should a query like this take to complete?

Try this
SelectQuery query = new SelectQuery("Win32_UserAccount", "LocalAccount=1 and Domain='" + GetMachine().DomainName + "'");
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher(query)) {
IList<WindowsUser> users = new List<WindowsUser>();
Console.WriteLine("Getting users...");
ManagementObjectCollection myCollection = searcher.Get();
foreach (ManagementObject envVar in MyCollection){
Console.WriteLine("Getting " + envVar["Name"].ToString() + "...");
}
}

Related

c# Print PDF with Adobe Reader and close

I didnt found a good (free) and simple Solution for printing PDFs (for e.g. from a "Hot"-Folder (FileSystemWatcher) on a Server) with Acrobat and close Acrobat Reader. So i wrote my own and i hope it will help someone.
(Yes, u can use a old free Foxit Reader Version, but we had too much trouble with it, sometimes stuck in Memory without printing)
The Point was, after printing, the file must be moved to a archive dir, but Adobe did not close. So i never knowed when its done, or wait 30+ Seconds and kill (not so fine if the Server needs longer and takes to much time).
Here my Solution, i run the Process and wait until one of the subprocesses of my Adobe Process shows the recent open Window.
Thanks to mtijn for his "Process Searcher" solution https://stackoverflow.com/a/7189381/480982
var prz = Process.Start("C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader\\AcroRd32.exe", "/h /t \"" + YOURPDFFILE + "\" \"" + YOURPRINTER + "\"");
bool loop = true;
while (loop)
{
//u can use Thread.Sleep(x) too;
prz.WaitForExit(500);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"SELECT * " +
"FROM Win32_Process " +
"WHERE ParentProcessId=" + prz.Id);
ManagementObjectCollection collection = searcher.Get();
if (collection.Count > 0)
{
foreach (var item in collection)
{
UInt32 childProcessId = (UInt32)item["ProcessId"];
if ((int)childProcessId != Process.GetCurrentProcess().Id)
{
Process childProcess = Process.GetProcessById((int)childProcessId);
//If a File is open the Title begins with "Filename - Adobe ...", but after print/closing the recent window starts with "Adobe Acr..."
if(childProcess.MainWindowTitle.StartsWith("Adobe Acrobat"))
{
loop = false;
break;
}
}
}
}
}
//"Recent" Window found, lets kill the Process
prz.Kill();
// Now here u can move or Delete the pdf file

Unable to get system hard drive SerialNumber using Win32_DiskDrive

I'm using the following code to get my drive serial number. It's working fine with Windows 7, 8, 8.1, and 10 Professional, but I'm getting an error on Windows 10 Home.
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject wmi_HD in searcher.Get())
{
if (wmi_HD["SerialNumber"] == null)
hddId = null;
else
hddId = wmi_HD["SerialNumber"].ToString();
}
I'm getting
System.NullReferenceException : Object reference not set to an instance of an object.
Does anyone know why? What do I need to do to get the serial number in this case?
One more question: if I boot the OS from my pendrive, will this code work? How could I know that the OS is running from a pendrive or disk or any other resource?
When I go to the Device Manager, I see this:
I am adding this as an answer because it can save lot of time while debugging scenarios like System.NullReferenceException in WMI.
Windows+R (run command)
Type wbemtest
And connect to the machine for which you want to fetch information. Fire the query for Win32_DiskDrive and check the output for properties that you can fetch.
This is what I'm using on Windows 10 v1809:
using System;
using System.Management;
namespace GetSerialNo
{
class Program
{
static void Main(string[] args)
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject info in searcher.Get())
{
Console.WriteLine("DeviceID: " + info["DeviceID"].ToString());
Console.WriteLine("Model: " + "Model: " + info["Model"].ToString());
Console.WriteLine("Interface: " + "Interface: " + info["InterfaceType"].ToString());
Console.WriteLine("Serial#: " + "Serial#: " + info["SerialNumber"].ToString());
}
Console.ReadLine();
}
}
}
For details please see http://csharphelper.com/blog/2017/10/get-hard-drive-serial-number-c/
For the associated link Get Hard disk serial Number given by #ADreNaLiNe-DJ I wasn't able to find the required assembly reference for HardDrive hd = new HardDrive();

C# Task Manager CPU Usage issue

I am trying to create an application that pulls process information and puts it into a SQL table.
I am pulling Process Name, PID, CPU Time, Memory Usage, Page, and Handles.
Everything works fine except for the CPU Time. Here is the code I am using to get the CPU information:
Process[] processes = Process.GetProcesses(machineName);
foreach (Process p in processes)
{
var cpuTime = p.TotalProcessorTime;
}
However I am getting this error:
Feature is not supported for remote machines.
Does anyone have any other way I can get this information and still be able to add it to my SQL table?
How about using WMI ?
string computerName="MyPc";
System.Management.ManagementScope ms = new System.Management.ManagementScope(#"\\" + computerName + #"\root\cimv2");
System.Management.SelectQuery sq = new System.Management.SelectQuery("SELECT * FROM Win32_Process");
System.Management.ManagementObjectSearcher mos = new System.Management.ManagementObjectSearcher(ms,sq);
foreach (System.Management.ManagementObject mo in mos.Get())
{
Console.WriteLine(mo["Name"].ToString());
}
Console.Read();

c# : How to Monitor Print job Using winspool_drv

Recently I am making a system monitoring tool. For that I need a class to monitor print job.
Such as when a print started, is it successful or not, how many pages.
I know that I can do it using winspool.drv. But dont how. I've searched extensively but having no luck. Any code/suggestion could be very helpful.
Thanks.
Well I don't know about the winspool.drv, but you can use the WMI to get the status of the printer. Here is an example of the using Win32_Printer.
PrintDialog pd = new PrintDialog();
pd.ShowDialog();
PrintDoc.PrinterSettings = pd.PrinterSettings;
PrintDoc.PrintPage += new PrintPageEventHandler(PrintDoc_PrintPage);
PrintDoc.Print();
object status = Convert.ToUInt32(9999);
while ((uint)status != 0) // 0 being idle
{
ManagementObjectSearcher mos = new ManagementObjectSearcher("select * from Win32_Printer where Name='" + pd.PrinterSettings.PrinterName + "'");
foreach (ManagementObject service in mos.Get())
{
status = service.Properties["PrinterState"].Value;
Thread.Sleep(50);
}
}
If you don't use the PrintDialog object (to choose a printer) you can run the WMI query and it will return all the printers in the system.

Get PC's Monitor Information Using .NET / WMI

Is there anyway using WMI/.Net to grab monitor information such as Manufacturer, Serial Number, Monitor Size etc.?
Using a script is an option as well, or can I query the registry directly to get this information?
SELECT * FROM Win32_DesktopMonitor doesn't really return any useful information for me in this case.
Hey, I use this tool for a lot of my WMI work, especially when prototyping and creating POCs....
Microsoft WMI Code Generator
This tool is great for creating quick console app code for any wmi query or method invocation in both C# and VB.NET
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DesktopMonitor");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_DesktopMonitor instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Description: {0}", queryObj["Description"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
The code above will get you the make and model of the monitor.
You may want to try this
https://raw.githubusercontent.com/MaxAnderson95/Get-Monitor-Information/master/Get-Monitor.ps1
Cheers
That select query should give you what you want. Here is the documentation which contains the details of the query.
Then you could do something like this:
public void GetMonitorDetails()
{
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor")
{
foreach(ManagementObject currentObj in searcher.Get())
{
String name = currentObj("Name").ToString();
String device_id = currentObj("DeviceID").ToString();
// ...
}
}
}
This post, combined with the answer below about the WMI management tool had my answer. Here is the code that returns your monitor resolutions.
try {
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\WMI",
"SELECT * FROM WmiMonitorBasicDisplayParams");
foreach (ManagementObject queryObj in searcher.Get()) {
Debug.WriteLine("-----------------------------------");
Debug.WriteLine("WmiMonitorBasicDisplayParams instance");
Debug.WriteLine("-----------------------------------");
Debug.WriteLine("Description: {0}", queryObj["SupportedDisplayFeatures"]);
}
} catch (ManagementException e) {
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
In my case, I'm still stuck, because it is returning the "scaled down" resolution of each monitor. One of mine is a 4K display, being reported as 2560x1440.

Categories

Resources