2 votes

Surveillance d'une imprimante

J'ai écrit une DLL qui surveille notre imprimante réseau. L'imprimante est connectée au serveur par un câble USB. Lorsque j'imprime quelque chose directement depuis le serveur, il affiche correctement les informations sur les pages envoyées/imprimées, mais lorsque j'imprime quelque chose depuis l'un des ordinateurs clients, il n'affiche que son IP, le nombre de pages envoyées/imprimées est toujours de 0.

Je suppose que c'est un défaut de l'API Winspooler, ma question est la suivante : y a-t-il un moyen de le contourner ?

Voici le code, pour ce qu'il vaut :

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);

            }
        }
    }
};

3voto

arul Points 10719

Je l'ai. L'imprimante réseau n'envoie que des informations de base si elle a été ajoutée automatiquement par Windows.

L'ajout manuel de l'imprimante a réglé le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X