-1

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?
dariush
  • 3,191
  • 3
  • 24
  • 43
  • Sounds like a rather dubious task. Isn't this better handled by the printer? – David Heffernan Aug 13 '15 at 08:40
  • The program needs the counts, it has nothing to do with the printer. – dariush Aug 13 '15 at 08:41
  • Do you want to do this for arbitrary printer types? What about print to file rather than print to paper? What if the print job is queued but never actually printed? Do you want to know the number of pages queued, or the number of pages printed? – David Heffernan Aug 13 '15 at 09:05
  • @DavidHeffernan 1) Yes, i want this for any arbitrary printer type, and it would be great if I can get to know the printer type in my callback function. 2) Nop, I only need the prints to papers, but if it is not possible its OK to count both files and papers#. 3) It does not matter if print never happened. 4) I want to know the printed pages, but if it is not possible the queued pages are OK too(I can write a work around for that) – dariush Aug 15 '15 at 14:22

1 Answers1

0

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);
}
dariush
  • 3,191
  • 3
  • 24
  • 43