C# Trying to get the printer status when it is offline - c#

I need to get the printer status when it is offline, below is how I am getting the status;
// Set management scope
ManagementScope scope = new ManagementScope(#"\root\cimv2");
scope.Connect();
// Select Printers from WMI Object Collections
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_Printer");
string printerName = "";
foreach (ManagementObject printer in searcher.Get())
{
printerName = printer["Name"].ToString();
if (printerName.Equals(#"TEC B-EV4-T"))
{
//Console.WriteLine("Printer = " + printer["Name"]);
if (printer.Properties["PrinterStatus"].Value.ToString() == "7")
{
// printer is offline by user
MessageBox.Show("TEC B-EV4-T is offline");
}
else
{
// printer is not offline
//Check API first then print
ReportDocument cryRpt = new ReportDocument();
cryRpt.Load(Environment.CurrentDirectory + "\\Report.rpt");
dialog.PrintQueue = new PrintQueue(new PrintServer(), "TEC B-EV4-T");
//to the data table here
//To data table
DataTable dt = ToDataTable(lotinstruct);
cryRpt.SetDataSource(dt);
cryRpt.PrintToPrinter(1, true, 0, 0);
//}
MessageBox.Show("Already save result please check label!");
}
}
}
The problem is here if (printer.Properties["PrinterStatus"].Value.ToString() == "7") it seems like the printer status is always 3 when I debug (printer status 3 means that it is idle 7 means that it is offline). Is there any way to find out if the printer TEC B-EV4-T is offline?

You can refer PrintQueue in built in .Net framework to check printer status. There are many properties in it to check different status:
string printerName = "TEC B-EV4-T";
var server = new LocalPrintServer();
PrintQueue queue = server.GetPrintQueue(printerName , Array.Empty<string>());
bool isOffline = queue.IsOffline;
bool isBusy = queue.IsBusy;

Don't use printer["PrinterStatus"]. You have to use printer["WorkOffline"] like below:
bool IsOffline = false;
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_Printer where Name='" + YourPrinter + "'");
foreach(ManagementObject printer in searcher.Get())
{
IsOffline = (bool)printer["WorkOffline"];
}
if (IsOffline)
{
...
}

Related

Retrieve LoggedOnUsers on Remote Machine

I'm building a C# application to monitor server and workstation workloads with WMI and WQL queries. I'm using WMI because it seems to be faster in comparison to powershell queries. My hardship starts when I try to retrieve logged on users on a remote machine. I figured I need to use the Win32_LoggedOnUser class. I have tried the following queries:
#"SELECT * FROM Win32_LoggedOnUser"
#"SELECT Antecedent FROM Win32_LoggedOnUser"
What I'm used to is to retrieve the desired value like this:
var cims = connection.getCimInstances(this, queryUser);
if (cims != null)
{
foreach (CimInstance cim in cims)
{
Komponenten.User user = new Komponenten.User();
user.Name = Convert.ToString(cim.CimInstanceProperties["Name"].Value);
users.Add(user);
}
}
where queryUser is one of the strings from above.
In both cases, I get a Win32_Account object in return, which seems to suggest - and the debugger seems to confirm - that I should use CimInstanceProperties["Name"].Value on the returned Win32_Account class again. But that's not working at all. Any ideas on how to get access to the CimInstanceProperties of a Win32_Account stored in a CimInstanceProperity ? I can't find anything on the respective Windows reference page (https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-loggedonuser) nor during my extensive google-search.
Thanks!
I ended up using the ManagementObject-Class and Regex to find the usernames after converting the Antecedent - Object to a string:
var users = new List<Komponenten.User>();
var searcher = this.connection.makeQuery(this, "SELECT * FROM Win32_LoggedOnUser");
if (searcher != null)
{
foreach (ManagementObject queryObj in searcher.Get())
{
Komponenten.User user = new Komponenten.User();
var win32_account = queryObj["Antecedent"].ToString();
string stripped = Regex.Replace(win32_account, "[^a-zA-Z=]+", "", RegexOptions.Compiled);
int end = stripped.LastIndexOf("=");
user.Name = stripped.Substring(end+1);
users.Add(user);
}
this.users = users;
An alternative which takes the LogonSession into account is:
var users = new List<Komponenten.User>();
var searcher = this.connection.makeQuery(this, "SELECT LogonId FROM Win32_LogonSession Where LogonType=2");
var Scope = this.connection.getScope(this, this.connection.getConnection());
if (searcher != null)
{
foreach (ManagementObject queryObj in searcher.Get())
{
ObjectQuery LQuery = new ObjectQuery("Associators of {Win32_LogonSession.LogonId=" + queryObj["LogonId"] + "} Where AssocClass=Win32_LoggedOnUser Role=Dependent");
ManagementObjectSearcher LSearcher = new ManagementObjectSearcher(Scope, LQuery);
foreach (ManagementObject LWmiObject in LSearcher.Get())
{
Komponenten.User user = new Komponenten.User();
user.Name = Convert.ToString(LWmiObject["Name"]);
users.Add(user);
}
}
this.users = users;
}
where this.connection.getConnection is a ConnectionsOption object depending on your respective domain and account data

Listing network printers

Trying to run the following (found here http://www.encodedna.com/2013/04/show-printers-using-wmi.htm ) to get a list of network printers but it only returns printers added to my machine
System.Management.ManagementScope objMS = new System.Management.ManagementScope(ManagementPath.DefaultPath);
objMS.Connect();
SelectQuery objQuery = new SelectQuery("SELECT * FROM Win32_Printer");
ManagementObjectSearcher objMOS = new ManagementObjectSearcher(objMS, objQuery);
System.Management.ManagementObjectCollection objMOC = objMOS.Get();
foreach (ManagementObject Printers in objMOC)
{
if (Convert.ToBoolean(Printers["Local"])) // LOCAL PRINTERS.
{
Console.WriteLine("Local :- " + Printers["Name"]);
}
if (Convert.ToBoolean(Printers["Network"])) // ALL NETWORK PRINTERS.
{
Console.WriteLine("Network :- " + Printers["Name"]);
}
}
I can view/add network printers in control panel. Just curious why it isn't showing them. Any thoughts?
Thanks!
Try:
foreach (string printerString in PrinterSettings.InstalledPrinters)
{
// do something
}

Get client machine's default printer when application is accessed through citrix

i have a windows application which insert client machine's default printer to database on application launch. It works perfectly in my solution. I use the following code to save this.
string GetDefaultPrinter()
{
string defaultprinter = "";
try
{
PrinterSettings settings = new PrinterSettings();
foreach (string printer in PrinterSettings.InstalledPrinters)
{
settings.PrinterName = printer;
if (settings.IsDefaultPrinter)
{
defaultprinter = printer;
string[] array_printer= defaultprinter.Split('\\');
defaultprinter= array_printer[3].ToString();
string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}'", defaultprinter);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection coll = searcher.Get();
foreach (ManagementObject localprinter in coll)
{
foreach (PropertyData property in localprinter.Properties)
{
// Console.WriteLine(string.Format("{0}: {1}", property.Name, property.Value));
//MessageBox.Show(property.Name+"-"+ property.Value);
if (property.Name == "ShareName")
{
defaultprinter = property.Value.ToString().Trim();
}
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("defaltprinter- "+defaultprinter+"-" + ex.Message);
}
return defaultprinter;
}<br>
If I host this application in citrix, then what should I do to perform the same function?
regards,
Sivajith S.

WMI: Get USB device description on insertion

How can I get a device Id and other description on insertion of USB device?
I've found an example how to get notified about USB device insertion/removal. But how to get device desrtiption info?
Here is my code snippet:
WqlEventQuery q;
ManagementScope scope = new ManagementScope("root\\CIMV2");
scope.Options.EnablePrivileges = true;
try
{
q = new WqlEventQuery();
q.EventClassName = "__InstanceDeletionEvent";
q.WithinInterval = new TimeSpan(0, 0, 3);
q.Condition = #"TargetInstance ISA 'Win32_USBControllerdevice'";
w = new ManagementEventWatcher(scope, q);
w.EventArrived += new EventArrivedEventHandler(USBRemoved);
w.Start();
}
... catch()....
UPDATE: Actually, it is a Serial COM device with USB connection. So there is no driveName property. How can I get USB description, which I can see in Device Manager? Does WMI provide this info with the notification about USB insertion?
Complete new answer according to your updated answer. You may check für any connected USB device:
ManagementScope sc =
new ManagementScope(#"\\YOURCOMPUTERNAME\root\cimv2");
ObjectQuery query =
new ObjectQuery("Select * from Win32_USBHub");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(sc, query);
ManagementObjectCollection result = searcher.Get();
foreach (ManagementObject obj in result)
{
if (obj["Description"] != null) Console.WriteLine("Description:\t" + obj["Description"].ToString());
if (obj["DeviceID"] != null) Console.WriteLine("DeviceID:\t" + obj["DeviceID"].ToString());
if (obj["PNPDeviceID"] != null) Console.WriteLine("PNPDeviceID:\t" + obj["PNPDeviceID"].ToString());
}
(see MSDN WMI tasks examples) for this)
or have a look into any COM ConnectedDevice
ManagementScope sc =
new ManagementScope(#"\\YOURCOMPUTERNAME\root\cimv2");
ObjectQuery query =
new ObjectQuery("Select * from Win32_SerialPort");
searcher = new ManagementObjectSearcher(sc, query);
result = searcher.Get();
foreach (ManagementObject obj in result)
{
if (obj["Caption"] != null) Console.WriteLine("Caption:\t" + obj["Description"].ToString());
if (obj["Description"] != null) Console.WriteLine("Description:\t" + obj["DeviceID"].ToString());
if (obj["DeviceID"] != null) Console.WriteLine("DeviceID:\t" + obj["PNPDeviceID"].ToString());
}
(see ActiveX Experts for further details on this)

Resolving the WMI DNS Host Name

I am trying to make a comparison between a machine name i have retrieved from AD, and the DNS Host Name i want to get using WMI from the machine.
I currently have:
foreach (SearchResult oneMachine in allMachinesCollected)
{
pcName = oneMachine.Properties["name"][0].ToString();
ConnectionOptions setupConnection = new ConnectionOptions();
setupConnection.Username = USERNAME;
setupConnection.Password = PASSWORD;
setupConnection.Authority = "ntlmdomain:DOMAIN";
ManagementScope setupScope = new ManagementScope("\\\\" + pcName + "\\root\\cimv2", setupConnection);
setupScope.Connect();
ObjectQuery dnsNameQuery = new ObjectQuery("SELECT * FROM Win32_ComputerSystem");
ManagementObjectSearcher dnsNameSearch = new ManagementObjectSearcher(setupScope, dnsNameQuery);
ManagementObjectCollection allDNSNames = dnsNameSearch.Get();
string dnsHostName;
foreach (ManagementObject oneName in allDNSNames)
{
dnsHostName = oneName.Properties["DNSHostName"].ToString();
if (dnsHostName == pcName)
{
shutdownMethods.ShutdownMachine(pcName, USERNAME, PASSWORD);
MessageBox.Show(pcName + " has been sent the reboot command");
}
}
}
}
But i get a ManagementException >> dnsHostName = oneName.Properties["DNSHostName"].ToString(); << here saying not found.
Any ideas?
Depending on the operating system you are connecting to this property will not be available. You can see from the documentation that it is not available on Windows 2000 and XP. However, it is available on the Win32_NetworkAdapterConfiguration class, but you will receive more than one object, which you will have to loop over to get the name as most of them will be null.
Also, dnsHostName = oneName.Properties["DNSHostName"].ToString(); is not correct. It should be dnsHostName = oneName.Properties["DNSHostName"].Value.ToString(). Again, if you decide to use Win32_NetworkAdapterConfiguration keep in mind that it can be null.

Categories

Resources