代码之家  ›  专栏  ›  技术社区  ›  arul

监视打印机[关闭]

  •  2
  • arul  · 技术社区  · 17 年前

    我已经写了一个DLL来监控我们的网络打印机。打印机通过USB电缆连接到服务器。当我直接从服务器打印内容时,它会显示有关正确发送/打印的页面的信息,但当我从某台客户端计算机打印内容时,它只显示其IP,发送/打印始终为0。

    我想这是winspooler API的一个缺点,我的问题是,有没有办法解决这个问题?

    以下是代码,说明它的价值:

    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);
    
                }
            }
        }
    };
    
    1 回复  |  直到 17 年前
        1
  •  3
  •   arul    17 年前

    知道了。如果网络打印机是由windows自动添加的,则它只发送基本信息。

    手动添加打印机修复了该问题。