Get number of printed pages using C# (system-wide)

2.5k Views Asked by At

I have been on this for almost 2 days, and I haven't accomplish anything!!
I have been assigned to write a program to count number of pages printed on windows OS.
As far as I know, I need to intercept printing events and count them internally. which I should use FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification.

I have assigned a callback function PrinterNotifyWaitCallback with following signature, and it gets fire multiple times when a printing event happens.

 public void PrinterNotifyWaitCallback(Object state, bool timedOut) { ... }

Problem:

I have some clue on why a printing event would fire PrinterNotifyWaitCallback multiple times, BUT I cannot distinguish the actual printing callback event among those multiple callbacks, which obviously it has to do with Object state but there is zero document on how to achieve my objective, which is counting the printed pages.

Questions:

  1. How to distinguish the actual printing callback of PrinterNotifyWaitCallback to count the total printed# of pages system wide?
  2. Is there any other better way to accomplish the task?
1

There are 1 best solutions below

1
On BEST ANSWER

I have found the solution roughly through WMI. For what it's worth I came up with following to count the printed pages.

lock (this._printStatusLast)
{
    // make a query to OS
    // TODO: make the printers exclude from counting in below query (defined by admin)
    ManagementObjectCollection pmoc = new ManagementObjectSearcher("SELECT Name, NotReadyErrors, OutofPaperErrors, TotalJobsPrinted, TotalPagesPrinted FROM Win32_PerfRawData_Spooler_PrintQueue").Get();
    Dictionary<String, PrintDetail> phs = new Dictionary<string, PrintDetail>();
    foreach (ManagementObject mo in pmoc)
    {
        // do not count everything twice!! (this is needed to for future developments on excluding printers from getting count)
        if (mo["name"].ToString().ToLower() == "_total") continue;
        PrintDetail pd = new PrintDetail();
        foreach (PropertyData prop in mo.Properties)
        {
            if (prop.Name.ToLower() == "name") continue;
            pd[prop.Name] = (UInt32)prop.Value;
        }
        phs.Add(mo["name"].ToString(), pd);
    }
    UInt32 count = 0;
    // foreach category
    foreach (var _key in phs.Keys.ToArray<String>())
    {
        // do not count if there where any errors
        if (phs[_key].HasError) continue;
        count += phs[_key].TotalPagesPrinted;
    }
    this.txtPrint.Text = count.ToString();
    this._printStatusLast = new Dictionary<string, PrintDetail>(phs);
}