Pregunta

He escrito un archivo DLL que supervisa nuestra impresora de red. La impresora está conectada al servidor mediante un cable USB. Cuando imprimo algo directamente desde el servidor, muestra información sobre las páginas enviadas / impresas correctamente, pero cuando imprimo algo desde una de las computadoras cliente, solo muestra su IP, el envío / impresión siempre es 0.

Supongo que este es un inconveniente de la API de winspooler, mi pregunta es, ¿hay alguna forma de evitarlo?

Aquí está el código, por lo que vale la pena:

typedef struct PRINTERMONITOR_API tagPRINTJOBINFO
{
    // name of the machine that printed
    char *machineName;
    // name of the document
    char *document;
    // total pages actually *printed*
    DWORD totalPages;
    // number of pages sent to the printer
    DWORD printed;
    // private: state of the printJob
    BOOL  done;
} printJobInfo_t;

//-------------------------------------------------------
// Function called when the print job event finishes
//-------------------------------------------------------
typedef void (*Callback)(printJobInfo_t *);

//-------------------------------------------------------
// Printer Monitor class
//-------------------------------------------------------
class PrinterMonitor
{
private:

    //-------------------------------------------------------
    // Handle to the printer.
    //-------------------------------------------------------
    HANDLE                  m_hPrinter;

    //-------------------------------------------------------
    // Handle to the notify object being set when print event
    // occurs.
    //-------------------------------------------------------
    HANDLE                  m_hNotify;

    //-------------------------------------------------------
    // Handle of our worker thread.
    //-------------------------------------------------------
    HANDLE                  m_hThread;

    //-------------------------------------------------------
    // Holds PRINTER_CHANGE_XXX_XXX information about current
    // event.
    //-------------------------------------------------------
    DWORD                   m_dwChanged;

    //-------------------------------------------------------
    // ID of the worker thread.
    //-------------------------------------------------------
    DWORD                   m_dwThreadId;

    //-------------------------------------------------------
    // Name of the printer.
    //-------------------------------------------------------
    char                    *m_pszPrinterName;

    //-------------------------------------------------------
    // Printer event snooping options.
    //-------------------------------------------------------
    PRINTER_NOTIFY_OPTIONS  *m_pOptions;

    //-------------------------------------------------------
    // Output of the event function.
    //-------------------------------------------------------
    PRINTER_NOTIFY_INFO     *m_pOutPut; 

    //-------------------------------------------------------
    // Shall we go away?
    //-------------------------------------------------------
    BOOL                    m_fExit;

public:
    //-------------------------------------------------------
    // Callback function called when the event fires.
    //-------------------------------------------------------
    Callback                m_fpCallback;

    //-------------------------------------------------------
    // Constructor
    // - name of the printer
    // - callback function
    //-------------------------------------------------------
    PrinterMonitor(char *printerName, Callback callback)
    {
        memset(this, 0, sizeof(PrinterMonitor)); // zero me
        m_fpCallback        = callback;
        m_pszPrinterName    = new char[strlen(printerName)];
        strcpy(m_pszPrinterName, printerName);
        m_pOptions          = new PRINTER_NOTIFY_OPTIONS;
        m_hThread           = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PrinterMonitor::StartMonitoring, this, CREATE_SUSPENDED, &m_dwThreadId);
    }

    //-------------------------------------------------------
    // Stop the worker thread and delete some shit
    //-------------------------------------------------------
    ~PrinterMonitor()
    {
        StopMonitor();
        delete(m_pOptions);
        delete[](m_pszPrinterName);
    }

    //-------------------------------------------------------
    // Run the monitor in a seperate thread
    //-------------------------------------------------------
    void RunMonitor()
    {
        ResumeThread(m_hThread);
    }

    //-------------------------------------------------------
    // Stop the monitor, noes.
    //-------------------------------------------------------
    void StopMonitor()
    {
        m_fExit = true;
    }

    //-------------------------------------------------------
    // Checks if this object is a valid monitor
    //-------------------------------------------------------
    BOOL CheckMonitor()
    {
        if(OpenPrinter(this->m_pszPrinterName, &this->m_hPrinter, NULL))
        {
            if(this->m_hPrinter != INVALID_HANDLE_VALUE)
            {
                ClosePrinter(this->m_hPrinter);
                return true;
            }
        }

        return false;
    }

private:
    //-------------------------------------------------------
    // The worker thread proc
    //-------------------------------------------------------
    static void WINAPI StartMonitoring(void *thisPtr)
    {

        PrinterMonitor* pThis = reinterpret_cast<PrinterMonitor*>(thisPtr);

        if(OpenPrinter(pThis->m_pszPrinterName, &pThis->m_hPrinter, NULL))
        {
            WORD wJobFields[5];
            wJobFields[0]           = JOB_NOTIFY_FIELD_STATUS;
            wJobFields[1]           = JOB_NOTIFY_FIELD_MACHINE_NAME;
            wJobFields[2]           = JOB_NOTIFY_FIELD_TOTAL_PAGES;
            wJobFields[3]           = JOB_NOTIFY_FIELD_PAGES_PRINTED;
            wJobFields[4]           = JOB_NOTIFY_FIELD_DOCUMENT;

            PRINTER_NOTIFY_OPTIONS_TYPE rOptions[1];
            rOptions[0].Type    = JOB_NOTIFY_TYPE;
            rOptions[0].pFields = &wJobFields[0];
            rOptions[0].Count   = 5;

            pThis->m_pOptions->Count    = 1;
            pThis->m_pOptions->Version  = 2;
            pThis->m_pOptions->pTypes   = rOptions;
            pThis->m_pOptions->Flags    = PRINTER_NOTIFY_OPTIONS_REFRESH;

            if((pThis->m_hNotify = 
                FindFirstPrinterChangeNotification(pThis->m_hPrinter, 0, 0, pThis->m_pOptions)) != INVALID_HANDLE_VALUE)
            {
                while(pThis->m_hNotify != INVALID_HANDLE_VALUE && !pThis->m_fExit)
                {
                    if(WaitForSingleObject(pThis->m_hNotify, 10) == WAIT_OBJECT_0)
                    {
                        FindNextPrinterChangeNotification(pThis->m_hNotify, &pThis->m_dwChanged, (LPVOID)pThis->m_pOptions, (LPVOID*)&pThis->m_pOutPut);

                        printJobInfo_t info = {0};
                        for (unsigned int i=0; i < pThis->m_pOutPut->Count; i++)
                        {
                            PRINTER_NOTIFY_INFO_DATA data = pThis->m_pOutPut->aData[i];

                            if(data.Type == JOB_NOTIFY_TYPE)
                            {
                                switch(data.Field
                                {
                                    case JOB_NOTIFY_FIELD_PAGES_PRINTED:
                                        {
                                            info.printed = data.NotifyData.adwData[0];
                                        }
                                        break;

                                    case JOB_NOTIFY_FIELD_MACHINE_NAME:
                                        {
                                            LPSTR name = (LPSTR) data.NotifyData.Data.pBuf;
                                            unsigned int length = strlen(name); 
                                            info.machineName = new char[length];
                                            strcpy(info.machineName, name);                                         
                                        }
                                        break;

                                    case JOB_NOTIFY_FIELD_TOTAL_PAGES:
                                        {
                                            info.totalPages = data.NotifyData.adwData[0];
                                        }
                                        break;

                                    case JOB_NOTIFY_FIELD_DOCUMENT:
                                        {
                                            LPSTR document = (LPSTR) data.NotifyData.Data.pBuf;
                                            unsigned int length = strlen(document);
                                            info.document = new char[length];
                                            strcpy(info.document, document);                                            
                                        }
                                        break;

                                    case JOB_NOTIFY_FIELD_STATUS:
                                        {
                                            if(data.NotifyData.adwData[0] & JOB_STATUS_PRINTED)
                                            {
                                                info.done = true;
                                            }
                                        }
                                        break;
                                }
                            }
                        }

                        if(info.done)
                        {
                            pThis->m_fpCallback(&info);

                            delete[](info.document);
                            delete[](info.machineName);
                        }
                    }
                }

                if(pThis->m_hPrinter != INVALID_HANDLE_VALUE)
                    ClosePrinter(pThis->m_hPrinter);

                if(pThis->m_hNotify != INVALID_HANDLE_VALUE)
                    FindClosePrinterChangeNotification(pThis->m_hNotify);

            }
        }
    }
};
¿Fue útil?

Solución

Lo tengo. La impresora de red solo envía información básica si fue agregada automáticamente por Windows.

La adición de la impresora solucionó el problema manualmente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top