Counting printed Pages by Clients with c# and WMI - c#

the goal is like i said in the Topic. I know there are a lot of articles on that specific Problem and i tried all most all of them.
But since non of them worked out for me, I'm now trying to find out why this one just works sometimes and sometimes nothing is happening although many things are printed.
So this is my code which right now should wait for a job to be printed and just tell me about it. Nothing more.
private void StartMonitor()
{
try
{
var opt = new ConnectionOptions { EnablePrivileges = true };
var scope = new ManagementScope("root\\CIMV2", opt);
scope.Connect();
var query = new WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 60 WHERE TargetInstance ISA \"Win32_PrintJob\"");
var watcher = new ManagementEventWatcher(query);
Console.WriteLine("Ready to receive Printer Job events...");
var pjEvent = watcher.WaitForNextEvent();
if (pjEvent != null) Console.WriteLine("Event occured: " + pjEvent.Properties["PagesPrinted"]);
}
catch (ManagementException e)
{
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.ErrorCode);
Console.WriteLine(e.ErrorInformation);
_Error = e.Message;
throw;
}
}

To get the progress of the printed pages for a particular job, try using a smaller polling interval and use the EventArrivedEventHandler delegate attached to the WMI event for handling the incoming data in a asynchronous way.
Try this sample.
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
public class EventWatcherAsync
{
private void WmiEventHandler(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("TargetInstance.Caption : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Caption"]);
Console.WriteLine("TargetInstance.JobStatus : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["JobStatus"]);
Console.WriteLine("TargetInstance.PagesPrinted : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["PagesPrinted"]);
Console.WriteLine("TargetInstance.Status : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Status"]);
}
public EventWatcherAsync()
{
try
{
string ComputerName = "localhost";
string WmiQuery;
ManagementEventWatcher Watcher;
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();
WmiQuery ="Select * From __InstanceOperationEvent Within 1 "+
"Where TargetInstance ISA 'Win32_PrintJob' ";
Watcher = new ManagementEventWatcher(Scope, new EventQuery(WmiQuery));
Watcher.EventArrived += new EventArrivedEventHandler(this.WmiEventHandler);
Watcher.Start();
Console.Read();
Watcher.Stop();
}
catch (Exception e)
{
Console.WriteLine("Exception {0} Trace {1}", e.Message, e.StackTrace);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Listening {0}", "__InstanceOperationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}

To get the total pages printed by a job I would try monitoring __InstanceDeletionEvents, I believe that at that time Win32_PrintJob.TotalPages should show the printed pages accurately (can't test this right now, sorry). There is also a nice alternative here:
Monitoring a Printer Queue from VB.NET
If you look at the article comments, the author also advises to monitor JOB_WRITTEN events to get the total number of pages printed.
If you are trying to monitor the progress of large print jobs, try monitoring __InstanceModificationEvents once the job is created, something like this:
Select * From __InstanceModificationEvent Within 1
Where TargetInstance Isa "Win32_PrintJob"
And TargetInstance.PagesPrinted > PreviousInstance.PagesPrinted

Related

Telegram Flood prevention

There was such a problem: I ran the program many times and now it throws the following error FloodException: Flood prevention. Telegram now requires your program to do requests again only after 73611 seconds have passed (TimeToWait property). If you think the culprit of this problem may lie in TLSharp's implementation, open a Github issue please.
I attach the code below:
using System;
using System.Text;
using System.Windows.Forms;
using TeleSharp.TL;
using TeleSharp.TL.Messages;
using TLSharp.Core;
namespace tgBM
{
public partial class Form1: Form
{
string phone;
string code;
int n = 1;
StringBuilder sb = new StringBuilder ();
TelegramClient client = new TelegramClient (2646156, "08ec188e0bdee432e568120348f5f13a"); // create a client with parameters
public Form1 ()
{
InitializeComponent();
}
string str = "";
public async void authAsync()
{
var dialogs = (TLDialogs) await client.GetUserDialogsAsync();
foreach (var element in dialogs.Chats)
{
TLChat chat = element as TLChat;
if (element is TLChannel)
{
var offset = 0;
TLChannel channel = element as TLChannel;
if (channel.Title == "TOPLES")
{
TLChannel ch = element as TLChannel;
TLInputPeerChannel inputPeer = new TLInputPeerChannel() {ChannelId = ch.Id, AccessHash = (long) ch.AccessHash};
while (n! = 11)
{
try
{
TLChannelMessages res = await client.SendRequestAsync <TLChannelMessages>
(new TLRequestGetHistory() {Peer = inputPeer, Limit = 20, AddOffset = offset, OffsetId = 0});
var msgs = res.Messages;
if (res.Count> offset)
{
offset + = msgs.Count;
foreach (TLAbsMessage msg in msgs)
{
if (msg is TLMessage)
{
TLMessage message = msg as TLMessage;
str + = n.ToString () + "\ t" + message.Id + "\ t" + message.FromId + "\ t" + message.Message + Environment.NewLine;
}
if (msg is TLMessageService)
continue;
n ++;
}
}
else
break;
}
catch (Exception ex)
{
MessageBox.Show (ex.Message);
break;
}
}
}
}
textBox3.Text = str;
}
}
private async void button1_Click (object sender, EventArgs e)
{
phone = textBox1.Text;
await client.ConnectAsync (); // make a connection
var hash = await client.SendCodeRequestAsync(phone);
}
private async void button2_Click (object sender, EventArgs e)
{
code = textBox2.Text;
var user = await client.MakeAuthAsync(phone, await client.SendCodeRequestAsync(phone), code);
authAsync();
}
}
}
In a comment, you said are in a testing phase.
In this case, you should read https://core.telegram.org/api/auth#test-accounts
According to this page, there are 3 ways to perform tests while limiting the risk for FLOOD_WAIT errors:
Connect to the Test servers instead of the Production servers (seems not possible with TLSharp)
Use Test accounts with phone numbers 99966XYYYY (only available on Test servers)
Connect as a user with the phone number you use to create the API ID/Hash
I can do all that with WTelegramClient (TLSharp is no longer maintained and cannot connect to Telegram servers anymore)

Using C# to access phone folders and read/write

Sorry if someone just posts a link to the answer, but I was really struggling to google this.
I can't figure out how to detect mobile phones when they're plugged in and then access their storage. The former is just something I don't know where to start looking and the second befuddles me a little because I'm used to accessing storage with a drive letter. The phones I've used (iPhone 4S and a few different Samsung galaxy's and notes) don't have a drive letter. So where would I start?
I use C# but I'm comfortable with the dllimports etc.
I've now done this code from the thread I linked in a comment above, nice and easy to throw into a program.
using System;
using System.Management;
using System.Threading;
namespace USBDeviceTester
{
class Program
{
static void Main(string[] args)
{
Thread myThread = new Thread(new ThreadStart(ThreadWorker));
myThread.Start();
}
public static void ThreadWorker()
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000000);
}
private static void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("");
Console.WriteLine(" --- DEVICE INSERTED ---");
Console.WriteLine("");
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
Console.WriteLine("");
}
static void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("");
Console.WriteLine(" --- DEVICE REMOVED ---");
Console.WriteLine("");
//ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
//foreach (var property in instance.Properties)
//{
// Console.WriteLine(property.Name + " = " + property.Value);
//}
}
}
}
Which returns information as so:
--- DEVICE REMOVED ---
--- DEVICE INSERTED ---
Availability =
Caption = Apple Mobile Device USB Driver
ClassCode =
ConfigManagerErrorCode = 0
ConfigManagerUserConfig = False
CreationClassName = Win32_USBHub
CurrentAlternateSettings =
CurrentConfigValue =
Description = Apple Mobile Device USB Driver
DeviceID = USB\VID_05AC&PID_12A0\3ABFD2ED02E3982B5F4455FD684716A6D4958A74
ErrorCleared =
ErrorDescription =
GangSwitched =
InstallDate =
LastErrorCode =
Name = Apple Mobile Device USB Driver
NumberOfConfigs =
NumberOfPorts =
PNPDeviceID = USB\VID_05AC&PID_12A0\3ABFD2ED02E3982B5F4455FD684716A6D4958A74
PowerManagementCapabilities =
PowerManagementSupported =
ProtocolCode =
Status = OK
StatusInfo =
SubclassCode =
SystemCreationClassName = Win32_ComputerSystem
SystemName = MyComputerName
USBVersion =

How to prevent WMI quotas from overflowing?

I am using a C# application to monitor the processes launched from a particular folder, and I am using WMI for monitoring. My WMI query is like
SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ExecutablePath LIKE '{0}%'
where I substitute the parameter with the path to the folder which I am intereseted. The WMI query is working fine and I am subscribing to the event notifications to do some additional processsing when a process from the particular folder comes up. The monitoring tool runs fine for hours after which I start getting a WMI QuotaViolation exception in my app. Once this happens I need to restart the Windows Management Instrumentation service to get the thing working.
I was initially using a
`SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'`
query and then checking the processes folder in the event notification, the modification in the query was done hoping it would reduce the result set and therefore prevent the Quota Violation.
Is there any way to flush the WMI quotas periodically or any other method whereby I can prevent the QuotaViolation? What is the best way to handle a QuotaViolation scenario?
Edit:
This is my process watcher object :
public class ProcessWatcher : ManagementEventWatcher
{
private string folder = "";
// Process Events
public event ProcessEventHandler ProcessCreated; //notifies process creation
//add any more event notifications required here
// WMI WQL process query strings
static readonly string WMI_OPER_EVENT_QUERY = #"SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'";
static readonly string WMI_OPER_EVENT_QUERY_WITH_PROC =
WMI_OPER_EVENT_QUERY + " and TargetInstance.Name = '{0}'";
public ProcessWatcher(string basepath)
{
folder = basepath;
Init(string.Empty);
}
public ProcessWatcher(string processName, string basepath)
{
folder = basepath;
Init(processName);
}
private void Init(string processName)
{
this.Query.QueryLanguage = "WQL";
if (string.IsNullOrEmpty(processName))
{
this.Query.QueryString = string.Format(WMI_OPER_EVENT_QUERY + #" AND TargetInstance.ExecutablePath LIKE '{0}%'", folder.Replace(#"\",#"\\")) ;
}
else
{
this.Query.QueryString =
string.Format(WMI_OPER_EVENT_QUERY_WITH_PROC, processName);
}
this.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
}
private void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
try
{
ManagementBaseObject mObj = e.NewEvent["TargetInstance"] as ManagementBaseObject;
if (mObj != null)
{
Win32_Process proc = new Win32_Process(mObj);
if (proc != null)
{
folder = folder.ToLower() ?? "";
string exepath = (string.IsNullOrEmpty(proc.ExecutablePath)) ? "" : proc.ExecutablePath.ToLower();
if (!string.IsNullOrEmpty(folder) && !string.IsNullOrEmpty(exepath) && exepath.Contains(folder))
{
if (ProcessCreated != null) ProcessCreated(proc);
}
}
proc.Dispose();
}
mObj.Dispose();
}
catch(Exception ex) { throw; }
finally
{
e.NewEvent.Dispose();
}
}
I create a ProcessWatcher object at app startup, in a viewmodel constructor like :
watch = new ProcessWatcher(BasePath);
watch.ProcessCreated += new ProcessEventHandler(procWatcher_ProcessCreated);
watch.Start();
The start call is where the QuotaViolation is raised if I try to start it a second time without restarting WMI.
At app exit, I am disposing off the ProcessWatcher object like :
watch.Stop();
watch.Dispose();
The Relevant Stack trace is :
Exception InnerException [System.Management.ManagementException: Quota violation
at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
at System.Management.ManagementEventWatcher.Start()
at App.ProcessTabViewModel1..ctor()
System.Management.ManagementException: Quota violation
Yes, that happens. I wrote a little test program, based on your snippet after adding the missing pieces:
static void Main(string[] args) {
for (int ix = 0; ix < 1000; ++ix) {
var obj = new ProcessWatcher("");
obj.ProcessCreated += obj_ProcessCreated;
obj.Start();
}
}
Kaboom! With the exact same stack trace as you quoted. It conked out at ix == 76. In other words, the WMI quota for this query is 75. Tested in Windows 8.1. Feels about right, this is a very expensive query, none too fast either.
You are going to have to do this fundamentally different, create only one query. One is enough, you probably got into trouble by doing this for many folders. Attack that differently, do your own filtering when you get the event. A rough example (I didn't quite get the filtering you want to do):
public class ProcessWatcher2 : IDisposable {
public delegate void ProcessCreateEvent(string name, string path);
public event ProcessCreateEvent ProcessCreated;
public ProcessWatcher2(string folder) {
this.folder = folder;
lock (locker) {
listeners.Add(this);
if (watcher == null) Initialize();
}
}
public void Dispose() {
lock (locker) {
listeners.Remove(this);
if (listeners.Count == 0) {
watcher.Stop();
watcher.Dispose();
watcher = null;
}
}
}
private static void Initialize() {
var query = new WqlEventQuery(#"SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'");
watcher = new ManagementEventWatcher(query);
watcher.EventArrived += watcher_EventArrived;
watcher.Start();
}
private static void watcher_EventArrived(object sender, EventArrivedEventArgs e) {
using (var proc = (ManagementBaseObject)e.NewEvent["TargetInstance"]) {
string name = (string)proc.Properties["Name"].Value;
string path = (string)proc.Properties["ExecutablePath"].Value;
lock (locker) {
foreach (var listener in listeners) {
bool filtered = false;
// Todo: implement your filtering
//...
var handler = listener.ProcessCreated;
if (!filtered && handler != null) {
handler(name, path);
}
}
}
}
}
private static ManagementEventWatcher watcher;
private static List<ProcessWatcher2> listeners = new List<ProcessWatcher2>();
private static object locker = new object();
private string folder;
}

WMI Files Montioring using C#

I am working on WMI(Windows Management Instrumentation) in C# and stuck at a point.
I have to create an application using WMI (C#) similar to File System Watcher.
I would like to get notified every time whenever within a particular folder a new file is created or deleted.
MY WQL query is :
SELECT * from _InstanceModificationEvent within 2 where TargetInstance ISA 'CIM_DataFile' and TargetInstance.Drive = 'C:' AND TargetInstance.Path='\\Test'
While running the query using wbemtest , it displays an Error message prompting Invalid Class.
Can someone please help me out regarding same?
In order to detect when a file is created , modified or deleted you must use the __InstanceOperationEvent WMI Class and the using the value of __Class property you can figure out out if the file was modified, deleted o created.
Try this sample
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
public class EventWatcherAsync
{
private void WmiEventHandler(object sender, EventArrivedEventArgs e)
{
// e.NewEvent
string wclass = ((ManagementBaseObject)e.NewEvent).SystemProperties["__Class"].Value.ToString();
string wop = string.Empty;
switch (wclass)
{
case "__InstanceModificationEvent":
wop = "Modified";
break;
case "__InstanceCreationEvent":
wop = "Created";
break;
case "__InstanceDeletionEvent":
wop = "Deleted";
break;
}
string wfilename = ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["FileName"].ToString();
if (!string.IsNullOrEmpty(((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Extension"].ToString()))
{
wfilename += "." + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Extension"].ToString();
}
Console.WriteLine(String.Format("The File {0} was {1}", wfilename, wop));
}
public EventWatcherAsync()
{
try
{
string ComputerName = "localhost";
string WmiQuery;
ManagementEventWatcher Watcher;
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();
//Check for changes in the path C:\Test
WmiQuery = #"Select * From __InstanceOperationEvent Within 1
Where TargetInstance ISA 'CIM_DataFile' and TargetInstance.Drive = 'C:' AND TargetInstance.Path='\\Test\\'";
Watcher = new ManagementEventWatcher(Scope, new EventQuery(WmiQuery));
Watcher.EventArrived += new EventArrivedEventHandler(this.WmiEventHandler);
Watcher.Start();
Console.Read();
Watcher.Stop();
}
catch (Exception e)
{
Console.WriteLine("Exception {0} Trace {1}", e.Message, e.StackTrace);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Listening {0}", "__InstanceOperationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}

How to subscribe a specific network adapter connection event in .NET

I have two network adapters in my machine. E.g. adapter A and adapter B. The A keeps connected
I want to monitor the connection status of adapter B. I mean, connected or disconnected status.
I tried the System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged
But it doesn't work, since the adapter A connected.
Maybe WMI is helpful, but I don't have any experience about it, also didn't find much useful article.
Could any one help to show me
how to subscribe WMI event of the adapter A connection status in C#
You can use the Win32_NetworkAdapter WMI class and the NetConnectionStatus property with the __InstanceModificationEvent event.
The WQL sentence will look like so
Select * From __InstanceModificationEvent Within 1 Where TargetInstance ISA 'Win32_NetworkAdapter' AND TargetInstance.Name='Network adapter name'
Try this sample
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
public class EventWatcherAsync
{
private void WmiEventHandler(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("TargetInstance.Name : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Name"]);
//2 (0x2) Connected
//7 (0x7) Media disconnected
Console.WriteLine("TargetInstance.NetConnectionStatus : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["NetConnectionStatus"]);
}
public EventWatcherAsync()
{
try
{
string ComputerName = "localhost";
string WmiQuery;
ManagementEventWatcher Watcher;
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();
WmiQuery ="Select * From __InstanceModificationEvent Within 1 "+
"Where TargetInstance ISA 'Win32_NetworkAdapter' AND TargetInstance.Name='Tarjeta Mini de media altura WLAN Wireless-N DW1501' ";
Watcher = new ManagementEventWatcher(Scope, new EventQuery(WmiQuery));
Watcher.EventArrived += new EventArrivedEventHandler(this.WmiEventHandler);
Watcher.Start();
Console.Read();
Watcher.Stop();
}
catch (Exception e)
{
Console.WriteLine("Exception {0} Trace {1}", e.Message, e.StackTrace);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Listening {0}", "__InstanceModificationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}

Categories