Search code examples
c#.neteventsunmanagedprint-spooler-api

FindNextPrinterChangeNotification misses events?


I am using FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification to catch printing events. However I have noticed that FindNextPrinterChangeNotification does not reliably returns all the events. I have found a guy with the same problem in this article.

Basically, when I debug my program, or put Sleep command like his suggestion when processing an event, FindNextPrinterChangeNotificationskips a lot of events. Also, most of the time I get a lot of SPOOLING status events but miss the DELETED status event (sometimes I get it, but most of the time I cannot), even though I already push the jobs to a Queue for later processing.

Does anyone have this problem too? Also, I am trying the Microsoft PDF Printer, The NumberOfPages increases as the SPOOLING events come, but the NumberOfPagesPrinted does not. Is it intended?

EDIT After some investigation, the events are not actually gone. If I call another print job, the previous events are fired (including the DELETING/DELETED status of previous print job). Can you please suggest what is the problem?

Here's the code for calling FindFirstPrinterChangeNotification:

    //We got a valid Printer handle.  Let us register for change notification....
    _changeHandle = FindFirstPrinterChangeNotification(_printerHandle, (int)PRINTER_CHANGES.PRINTER_CHANGE_JOB, 0, _notifyOptions);
    // We have successfully registered for change notification.  Let us capture the handle...
    _mrEvent.SafeWaitHandle = new Microsoft.Win32.SafeHandles.SafeWaitHandle(_changeHandle, true);
    //Now, let us wait for change notification from the printer queue....
    _waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);

And this is for the FindNextPrinterChangeNotification:

    _notifyOptions.Count = 1;
    _notifyOptions.dwFlags = PRINTER_NOTIFY_OPTIONS_REFRESH;
    int pdwChange = 0;
    IntPtr pNotifyInfo = IntPtr.Zero;
    bool bResult = FindNextPrinterChangeNotification(_changeHandle, out pdwChange, _notifyOptions, out pNotifyInfo);

Solution

  • I had the same issue then I tried:

    _waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);    
    

    with:

    _waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, false);
    

    (false arg in the end) and seems to work now