2008-10-06 6 views
2

J'ai écrit une DLL qui surveille notre imprimante netowork. L'imprimante est connectée au serveur via un câble USB. Lorsque j'imprime quelque chose directement à partir du serveur, il affiche des informations sur les pages envoyées/imprimées correctement, mais lorsque j'imprime quelque chose sur l'un des ordinateurs clients, il n'affiche que son IP, envoyé/imprimé est toujours 0.Surveillance d'une imprimante

est une lacune de l'API de winspooler, ma question est, est-il possible de contourner le problème?

est ici le code, pour ce que ça 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); 

      } 
     } 
    } 
}; 

Répondre

3

Got it. L'imprimante réseau envoie uniquement des informations de base si elle a été ajoutée automatiquement par Windows. L'ajout de l'imprimante a résolu le problème manuellement.