Enumerating jobs in print queue
By Sergey - Posted on May 8th, 2008
Enumerating jobs in print queue can be done with
- WMI Win32_PrintJob class
- Windows API EnumJobs function.
| This is sample code. Add error handling and adjust to your requirements as necessary. |
&& WMI LOCAL lcPrinterName, lcComputer, loWMIService, loErr lcPrinterName = GETPRINTER() loLocator = CREATEOBJECT('WBEMScripting.SWBEMLocator') loWMI = loLocator.ConnectServer() && local machine logged on user loWMI.Security_.ImpersonationLevel = 3 && Impersonate lcPrinterName = STRTRAN(lcPrinterName , "\", "\\") loPrintJobs = loWMI.ExecQuery("Select * from Win32_PrintJob " + ; " WHERE Name LIKE '" + lcPrinterName + "%'") llOK = .T. TRY FOR EACH loPrintJob in loPrintJobs ? "---------------------------------------------" ? "Caption", loPrintjob.Caption ? "DataType", loPrintjob.DataType ? "Description", loPrintjob.Description ? "Document", loPrintjob.Document ? "DriverName", loPrintjob.DriverName ? "ElapsedTime", loPrintjob.ElapsedTime ? "HostPrintQueue", loPrintjob.HostPrintQueue ? "InstallDate", loPrintjob.InstallDate ? "JobId", loPrintjob.JobId ? "JobStatus", loPrintjob.JobStatus ? "Name", loPrintjob.Name ? "Notify", loPrintjob.Notify ? "Owner", loPrintjob.Owner ? "PagesPrinted", loPrintjob.PagesPrinted ? "Parameters", loPrintjob.Parameters ? "PrintProcessor", loPrintjob.PrintProcessor ? "Priority", loPrintjob.Priority ? "Size", loPrintjob.Size ? "StartTime", loPrintjob.StartTime ? "Status", loPrintjob.Status ? "StatusMask", loPrintjob.StatusMask ? "TimeSubmitted", loPrintjob.TimeSubmitted ? "TotalPages", loPrintjob.TotalPages ? "UntilTime", loPrintjob.UntilTime ENDFOR CATCH TO loErr ? loErr.Errorno, loErr.Message llOK = .F. ENDTRY
It's quite simple to enumerate jobs in print queue using Windows API, but it is complicated to retrieve information about jobs because it's returned as C/C++ structure and VFP doesn't have built-in capabilities to work with structures. The Windows API support class is used to handle Windows API structures.
The code requires VFP8 or later to run because it uses collection class to store Job info but it can be easily adapted to work under previous versions of VFP. It retrieves all info about a job stored in JOB_INFO_1 structure but date and time when job was submitted.
The WinApiErrMsg function in the code below is from Retrieving Windows system error message.
&& Windows API ooo = NEWOBJECT("EnumJobs", "EnumJobsClass.fxp") && Tretreive Jobs for default VFP printer IF NOT ooo.GetJobList() ? ooo.cErrorMessage ? ooo.cApiErrorMessage && Error ENDIF FOR i=1 TO ooo.oJobList.Count loOneJob = ooo.oJobList.Item(i) ? loOneJob.JobId, loOneJob.Document ENDFOR ooo = Null RETURN &&-------------------------------------------------------------------- &&EnumJobs.prg DEFINE CLASS EnumJobs AS Custom HIDDEN hHeap cPrinterName = "" cApiErrorMessage = "" cErrorMessage = "" hHeap = 0 oJobList = NULL oWas = NULL PROCEDURE Init() This.oJobList = CREATEOBJECT("Collection") This.oWas = NEWOBJECT("WinApiSupport", "WinApiSupport.fxp") This.LoadApiDlls() This.hHeap = HeapCreate(0, 4096, 0) && Use Windows default printer This.cPrinterName = SET("Printer",2) ENDPROC PROCEDURE Destroy IF This.hHeap <> 0 HeapDestroy(This.hHeap) ENDIF ENDPROC PROCEDURE GetJobList(tcPrinterName) LOCAL lhPrinter, llSuccess, lnNeeded, lnNumberOfJobs, lnBuffer, i, loOneJob IF PCOUNT() > 0 This.cPrinterName = tcPrinterName ENDIF This.ClearErrors() lhPrinter = 0 IF OpenPrinter(This.cPrinterName, @lhPrinter, 0) = 0 This.cErrorMessage = "Unable to get printer handle for '" + This.cPrinterName + "." This.cApiErrorMessage = WinApiErrMsg(GetLastError()) RETURN .F. ENDIF lnNeeded = 0 lnNumberOfJobs = 0 && Get the size of the buffer in lnNeeded IF EnumJobs(lhPrinter, 0, 127, 1, 0, 0, @lnNeeded, @lnNumberOfJobs ) = 0 IF GetLastError() <> 122 && The buffer too small error This.cErrorMessage = "Unable to Enumerate Jobs." This.cApiErrorMessage = WinApiErrMsg(GetLastError()) RETURN .F. ENDIF ENDIF && Allocate the buffer of required size and call EnumJobs again lnBuffer = HeapAlloc(This.hHeap, 0, lnNeeded) llSuccess = .T. IF EnumJobs(lhPrinter, 0, 127, 1, lnBuffer, @lnNeeded, @lnNeeded, @lnNumberOfJobs) = 0 This.cErrorMessage = "Unable to Enumerate Jobs." This.cApiErrorMessage = WinApiErrMsg(GetLastError()) llSuccess = .F. ENDIF IF llSuccess FOR i=1 TO lnNumberOfJobs loOneJob = This.OneJobObj() WITH loOneJob lnPointer = lnBuffer + (i-1) * 64 .JobId = This.oWas.Long2NumFromBuffer(lnPointer) .PrinterName = This.oWas.StrZFromBuffer(lnPointer+4) .MachineName = This.oWas.StrZFromBuffer(lnPointer+8) .UserName = This.oWas.StrZFromBuffer(lnPointer+12) .Document = This.oWas.StrZFromBuffer(lnPointer+16) .Datatype = This.oWas.StrZFromBuffer(lnPointer+20) .StatusText = This.oWas.StrZFromBuffer(lnPointer+24) .Status = This.oWas.Long2NumFromBuffer(lnPointer+28) .Priority = This.oWas.Long2NumFromBuffer(lnPointer+32) .Position = This.oWas.Long2NumFromBuffer(lnPointer+36) .TotalPages = This.oWas.Long2NumFromBuffer(lnPointer+40) .PagesPrinted = This.oWas.Long2NumFromBuffer(lnPointer+44) ENDWITH This.oJobList.Add(loOneJob, TRANSFORM(loOneJob.JobId)) ENDFOR ENDIF = HeapFree(This.hHeap, 0, lnBuffer ) = ClosePrinter(lhPrinter) RETURN llSuccess PROCEDURE OneJobObj LOCAL loOneJob loOneJob = NEWOBJECT("Empty") ADDPROPERTY(loOneJob, "JobId", 0) ADDPROPERTY(loOneJob, "PrinterName", "") ADDPROPERTY(loOneJob, "MachineName", "") ADDPROPERTY(loOneJob, "UserName", "") ADDPROPERTY(loOneJob, "Document", "") ADDPROPERTY(loOneJob, "Datatype", "") ADDPROPERTY(loOneJob, "StatusText", "") ADDPROPERTY(loOneJob, "Status", 0) ADDPROPERTY(loOneJob, "Priority", 0) ADDPROPERTY(loOneJob, "Position", 0) ADDPROPERTY(loOneJob, "TotalPages", 0) ADDPROPERTY(loOneJob, "PagesPrinted", 0) && SYSTEMTIME Submitted RETURN loOneJob ENDPROC PROCEDURE ClearErrors This.cErrorMessage = "" This.cApiErrorMessage = "" ENDPROC HIDDEN PROCEDURE LoadApiDlls DECLARE Long HeapCreate IN Win32API; Long dwOptions, Long dwInitialSize, Long dwMaxSize DECLARE Long HeapAlloc IN Win32API; Long hHeap, Long dwFlags, Long dwBytes DECLARE lstrcpy IN Win32API; String @lpString1, Long lpString2 DECLARE Long HeapFree IN Win32API; Long hHeap, Long dwFlags, Long lpMem DECLARE HeapDestroy IN WIN32API Long hHeap DECLARE Long GetLastError IN kernel32 ENDPROC ENDDEFINE &&---------------------------------------------------------------------------------------------- FUNCTION OpenPrinter(tcPrinterName, thPrinter, tcDefault) DECLARE Long OpenPrinter IN WinSpool.Drv ; String pPrinterName, Long@ phPrinter, String pDefault RETURN OpenPrinter(tcPrinterName, @thPrinter, tcDefault) FUNCTION ClosePrinter (thPrinter) DECLARE Long ClosePrinter IN WinSpool.Drv Long hPrinter RETURN ClosePrinter(thPrinter) FUNCTION EnumJobs(thPrinter, tnFirstJob, tnNoJobs, tnLevel, ; tnJob, tnBuf, tnNeeded, tnReturned) DECLARE Long EnumJobs IN WinSpool.Drv ; Long hPrinter, Long FirstJob, Long NoJobs, Long Level, ; Long pJob, Long cbBuf, Long @pcbNeeded, Long @pcReturned RETURN EnumJobs(thPrinter, tnFirstJob, tnNoJobs, tnLevel, ; tnJob, tnBuf, @tnNeeded, @tnReturned)
Recent comments
2 weeks 19 hours ago
2 weeks 1 day ago
2 weeks 1 day ago
5 weeks 1 day ago
9 weeks 6 days ago
9 weeks 6 days ago
10 weeks 4 days ago
11 weeks 3 days ago
12 weeks 6 days ago
12 weeks 6 days ago