No announcement yet.

Monitoring Print Jobs (Question to Jose Roca)

  • Filter
  • Time
  • Show
Clear All
new posts

    Monitoring Print Jobs (Question to Jose Roca)


    I modified your WMI code to write log for print jobs completed as follows:
    #DIM ALL
    #INCLUDE ""
    GLOBAL bFinish AS LONG
    GLOBAL TerminateAt AS STRING
    SUB DoWMI(strComputer AS ASCIIZ, sLogFile AS ASCIIZ)
        LOCAL hr AS LONG                     ' // HRESULT
        LOCAL CLSID_WbemLocator AS GUID      ' // IWbemLocator interface CLSID
        LOCAL IID_IWbemLocator AS GUID       ' // IWbemLocator interface IID
        LOCAL ppLocator AS DWORD PTR         ' // IWbemLocator interface reference
        LOCAL sThis AS STRING                ' // Error message to log
        LOCAL ppEnum AS DWORD PTR            ' // IEnumWbemClassObject collection reference
        LOCAL ppObject AS DWORD PTR          ' // IWbemClassObject interface reference
        LOCAL ppServices AS DWORD PTR        ' // IWbemServices interface reference
        LOCAL puReturned AS DWORD            ' // Number of returned references
        LOCAL varRecord AS VARIANT           ' // PrintJob record
        LOCAL oPrintJob AS DISPATCH          ' // PrintJob object
        LOCAL vProperty AS VARIANT           ' // The property value of a printjob property (variant)
        LOCAL sPrintJobName AS STRING        ' // The name of the printjob (string)
        LOCAL sPrintJobCaption AS STRING     ' // The caption property of the printJob
        LOCAL sPrintJobDataType AS STRING
        LOCAL sPrintJobDescription AS STRING
        LOCAL sPrintJobDocument AS STRING
        LOCAL sPrintJobDriverName AS STRING
        LOCAL sPrintJobElapsedTime AS STRING
        LOCAL sPrintJobHostPrintQueue AS STRING
        LOCAL sPrintJobInstallDate AS STRING
        LOCAL sPrintJobJobId AS LONG
        LOCAL sPrintJobJobStatus AS STRING
        LOCAL sPrintJobNotify AS STRING
        LOCAL sPrintJobOwner AS STRING
        LOCAL sPrintJobPagesPrinted AS LONG
        LOCAL sPrintJobPaperLength AS LONG
        LOCAL sPrintJobPaperSize AS STRING
        LOCAL sPrintJobPaperWidth AS LONG
        LOCAL sPrintJobParameters AS STRING
        LOCAL sPrintJobPrintProcessor AS STRING
        LOCAL sPrintJobPriority AS LONG
        LOCAL sPrintJobSize AS LONG
        LOCAL sPrintJobStartTime AS STRING
        LOCAL sPrintJobStatus AS STRING
        LOCAL sPrintJobStatusMask AS LONG
        LOCAL sPrintJobTimeSubmitted AS STRING
        LOCAL sPrintJobTotalPages AS LONG
        LOCAL sPrintJobUntilTime AS STRING
        LOCAL v AS LONG
        IF LEN(strComputer) = 0 THEN strComputer = "."
        ' // registers security and sets the default security values for the process
        hr = CoInitializeSecurity(BYVAL %NULL, -1, %NULL, %NULL, _
                                %RPC_C_AUTHN_LEVEL_CONNECT, %RPC_C_IMP_LEVEL_IMPERSONATE, %NULL, _
                                %EOAC_NONE, BYVAL %NULL)
        IF hr <> %S_OK THEN
            sThis = "CoInitializeSecurity failed with an error code of &H" & HEX$(hr)
            'log the error here
            EXIT SUB
        END IF
        ' // create a WbemLocator object
        CLSID_WbemLocator = $CLSID_WbemLocator
        IID_IWbemLocator = $IID_IWbemLocator
        hr = CoCreateInstance(CLSID_WbemLocator, BYVAL %NULL, %CLSCTX_INPROC_SERVER, _
                             IID_IWbemLocator, ppLocator)
        sThis = "ppLocator = " & STR$(ppLocator)
        'log the error here
        IF ISTRUE hr OR ppLocator = %NULL THEN
            v = FREEFILE
            OPEN sLogFile FOR APPEND AS #v
            PRINT #v, "Unable to load WbemLocator"
            CLOSE #v
            GOTO Terminate  'log the error before
        END IF
        hr = IWbemLocator_ConnectServer(ppLocator, "root\cimv2", BYVAL %NULL, BYVAL %NULL, _
                                    BYVAL %NULL, 0, BYVAL %NULL, %NULL, ppServices)
        sThis = "ppServices = " & STR$(ppServices)
        IF ISTRUE hr OR ppServices = %NULL THEN
            v = FREEFILE
            OPEN sLogFile FOR APPEND AS #v
            PRINT #v, "Unable to connect to service"
            CLOSE #v
            GOTO Terminate  'log the error before
        END IF
        hr = IWbemServices_ExecNotificationQuery(ppServices, "WQL", "Select * From __InstanceCreationEvent " _
                    & "Within 10 Where TargetInstance ISA 'Win32_PrintJob'", _
        IF ISTRUE hr OR ppEnum = %NULL THEN
            v = FREEFILE
            OPEN sLogFile FOR APPEND AS #v
            PRINT #v, "Unable to load PrintJobs"
            CLOSE #v
            GOTO Terminate  'log the error before
        END IF
        DO WHILE ISTRUE(bFinish)
            IF TIME$ > TerminateAt THEN bFinish = %FALSE
            ppObject = %NULL
            'hr = IEnumWbemClassObject_Next(ppEnum, 10, 1, BYVAL VARPTR(ppObject), puReturned)
            hr = WMIEXTENSIONLibISWbemEventSource_NextEvent(ppEnum, 5, BYVAL VARPTR(ppObject))
            IF NOT ppObject = %NULL THEN
                 ' // get the PrintJob
                hr = IWbemClassObject_Get(ppObject, "TargetInstance", 0, varRecord, %NULL, %NULL)
                SET oPrintJob = varRecord
                OBJECT GET oPrintJob.Name TO vProperty: sPrintJobName = VARIANT$(vProperty)
                OBJECT GET oPrintJob.Caption TO vProperty: sPrintJobCaption = VARIANT$(vProperty)
                OBJECT GET oPrintJob.DataType TO vProperty: sPrintJobDataType = VARIANT$(vProperty)
                OBJECT GET oPrintJob.Description TO vProperty: sPrintJobDescription = VARIANT$(vProperty)
                OBJECT GET oPrintJob.Document TO vProperty: sPrintJobDocument = VARIANT$(vProperty)
                OBJECT GET oPrintJob.DriverName TO vProperty: sPrintJobDriverName = VARIANT$(vProperty)
                OBJECT GET oPrintJob.ElapsedTime TO vProperty: sPrintJobElapsedTime = VARIANT$(vProperty)    'datetime
                OBJECT GET oPrintJob.HostPrintQueue TO vProperty: sPrintJobHostPrintQueue = VARIANT$(vProperty)
                OBJECT GET oPrintJob.InstallDate TO vProperty: sPrintJobInstallDate = VARIANT$(vProperty)    'datetime
                OBJECT GET oPrintJob.JobId TO vProperty: sPrintJobJobId = VARIANT#(vProperty)
                OBJECT GET oPrintJob.JobStatus TO vProperty: sPrintJobJobStatus = VARIANT$(vProperty)
                OBJECT GET oPrintJob.Notify TO vProperty: sPrintJobNotify = VARIANT$(vProperty)
                OBJECT GET oPrintJob.Owner TO vProperty: sPrintJobOwner = VARIANT$(vProperty)
                OBJECT GET oPrintJob.PagesPrinted TO vProperty: sPrintJobPagesPrinted = VARIANT#(vProperty)
                OBJECT GET oPrintJob.PaperLength TO vProperty: sPrintJobPaperLength = VARIANT#(vProperty)
                OBJECT GET oPrintJob.PaperSize TO vProperty: sPrintJobPaperSize = VARIANT$(vProperty)
                OBJECT GET oPrintJob.PaperWidth TO vProperty: sPrintJobPaperWidth = VARIANT#(vProperty)
                OBJECT GET oPrintJob.Parameters TO vProperty: sPrintJobParameters = VARIANT$(vProperty)
                OBJECT GET oPrintJob.PrintProcessor TO vProperty: sPrintJobPrintProcessor = VARIANT$(vProperty)
                OBJECT GET oPrintJob.Priority TO vProperty: sPrintJobPriority = VARIANT#(vProperty)
                OBJECT GET oPrintJob.Size TO vProperty: sPrintJobSize = VARIANT#(vProperty)
                OBJECT GET oPrintJob.StartTime TO vProperty: sPrintJobStartTime = VARIANT$(vProperty)    'datetime
                OBJECT GET oPrintJob.Status TO vProperty: sPrintJobStatus = VARIANT$(vProperty)
                OBJECT GET oPrintJob.StatusMask TO vProperty: sPrintJobStatusMask = VARIANT#(vProperty)
                OBJECT GET oPrintJob.TimeSubmitted TO vProperty: sPrintJobTimeSubmitted = VARIANT$(vProperty)    'datetime
                OBJECT GET oPrintJob.TotalPages TO vProperty: sPrintJobTotalPages = VARIANT#(vProperty)
                OBJECT GET oPrintJob.UntilTime TO vProperty: sPrintJobUntilTime = VARIANT$(vProperty)    'datetime
                v = FREEFILE
                OPEN sLogFile FOR APPEND AS #v
                PRINT #v, "<PrintJob Name=""" & sPrintJobName & """ Document=""" & sPrintJobDocument & """ ElapsedTime=""" & sPrintJobElapsedTime & """";
                PRINT #v, " JobId=""" & FORMAT$(sPrintJobJobId) & """ JobStatus=""" & sPrintJobJobStatus & """ Owner=""" & sPrintJobOwner & """ PagesPrinted=""" & FORMAT$(sPrintJobPagesPrinted) & """";
                PRINT #v, " PaperLength=""" & FORMAT$(sPrintJobPaperLength) & """ PaperWidth=""" & FORMAT$(sPrintJobPaperWidth) & """ PaperSize=""" & sPrintJobPaperSize & """";
                PRINT #v, " JobSize=""" & FORMAT$(sPrintJobSize) & """ StartTime=""" & sPrintJobStartTime & """ TimeSubmitted=""" & sPrintJobTimeSubmitted & """ TotalPages=""" & FORMAT$(sPrintJobTotalPages) & """";
                PRINT #v, " UntilTime=""" & sPrintJobUntilTime & """/>"
                CLOSE #v
                ' // release the collection's object
                IWbemClassObject_Release ppObject
            END IF
        ' // release the collection
        IF ISTRUE ppEnum THEN IEnumWbemClassObject_Release ppEnum
       IF ISTRUE ppServices THEN IWbemServices_Release ppServices
       IF ISTRUE ppLocator THEN IWbemLocator_Release ppLocator
       LOCAL tTimer AS LONG
       tTimer = GetTickCount
       LOOP UNTIL GetTickCount - tTimer > 20000
        LOCAL strComputer AS ASCIIZ * %MAX_PATH
        LOCAL sLogfile AS ASCIIZ * %MAX_PATH
        bFinish = %TRUE
        TerminateAt = "15:00:00" '<---------------- adjust the value as needed to unload!
        sLogfile    = "c:\apu\printlog.txt" '<----- adjust the value to your computer!
        DoWMI strComputer, sLogfile
        MSGBOX "Done"
    In order to incorporate the NextEvent method I modified TB_WMI.INC, added reference to the WMIExtensionLib as
    #INCLUDE ""

    and I created the include file using your utility.

    However, NextEvent never returns a valid object even when I am printing something. Doing the same in VB works. What am I doing wrong?


    Peter Redei
    Last edited by Peter Redei; 22 Mar 2008, 05:59 PM.

    Doing the same in VB works.
    Are you also using a timeout of 5 milliseconds with VB or are you using something like Set objEventObject = objEventSource.NextEvent() ? With VB, if you don't specify the timeout it defaults to -1 (infinite).

    Which value returns this call in hr?

    hr = WMIEXTENSIONLibISWbemEventSource_NextEvent(ppEnum, 5, BYVAL VARPTR(ppObject))

    If hr = &H80043001 it means that the equested event did not arrive in the amount of time specified in iTimeoutMs.


      Hi Jose,

      I tried it with different timeouts and I always got the same hr=&H40004 response that I believe means 'There is no connection for this connection ID', but I am not sure. In VB I got the response with 10 milliseconds timeout. I used timeout and not -1 because I did not want the program halt at the hr = WMIEXTENSIONLibISWbemEventSource_NextEvent(ppEnum, 10, BYVAL VARPTR(ppObject)) line until a print job is issued, so I can terminate the loop by changing the bFinish value.
      Setting the timeout to -1 halts the application even when I am printing. Any timeout value always returns &H40004 that is not documented by Microsoft as possible error. ppEnum seems to have a valid value.

      First time I tried this from VB it worked. I retried it now and it did not work either! Actually it did in about once from twenty attempts. Setting different timeouts in the query expression and in the timeout value does not show any affect.

      The original code is from Microsoft at

      I figured out what was the problem why the event was not fired. In the SQL statement I had to put very small timeout (0.1 milliseconds). Than I got response from VB or from script, but still not from PowerBasic. I tried this both in synchronous and in asynchronous (creating a sink object and using IWbemServices_ExecNotificationQueryAsync) with success in VB and faliure in PB.


      Peter Redei
      Last edited by Peter Redei; 24 Mar 2008, 04:30 PM.