Howdy,
I'm a little new to interoping, so I need a little help.
I have a WaitCallback method that raises an event whenever a job has been added to the print queue on the local machine (generally a print server). The primary purpose is to pause all incoming jobs so they can be properly logged, and then released afterwards. The jobs are stored in a queue in a separate SQL database.
This is all well and good when a user adds a printer through the "Add Printer..." dialog. However, whenever UPnP discovers a printer and automatically adds it, the jobs sent through that device raise multiple JobAdded events.
As an example, let's say we have a Xerox Document Centre 432 on the print server \\beast. If I share this printer on a network with the computer \\lappy-486, UPnP will automatically detect this printer and add it to the Printers and Faxes section of \\lappy-486 as "Auto Xerox Document Centre 432 on beast". If I manually add the printer through the Add A Printer Dialog, the printer will show as "Xerox Document Centre 432 on beast". Both of these reference the same printer. However, only the latter uses the driver installed on \\beast, if I'm not mistaken.
Typically, most of the jobs will come in flagged as "JOB_STATUS_DELETED | JOB_STATUS_DELETING". However, about 2-3 of the print attempts come into the printer as JOB_STATUS_SPOOLING, and don't respond to a SetJob command. Most of my interoping has to do with winspool.drv:
[
DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter(String pPrinterName, ref Int32 phPrinter, Int32 pDefault);
[DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter(String pPrinterName, ref IntPtr hPrinter, Int32 pDefault);
[DllImport("winspool.drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(Int32 hPrinter);
[DllImport("winspool.drv", EntryPoint = "GetJobA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern Int32 GetJob(Int32 hPrinter, Int32 dwJobId, JOB_INFO_LEVELS Level, IntPtr pJobInfo, Int32 cbBuf, ref Int32 lpbSizeNeeded);
[DllImport("winspool.drv", EntryPoint = "SetJobW", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool SetJob(Int32 hPrinter, Int32 dwJobId, Int32 Level, IntPtr lpJob, Print_Job_Control_Commands dwCommand);
Essentially, my solution is simply to check to see if the print job is suspended in a JOB_STATUS_SPOOLING state, and query the printer for any jobs that haven't been added to the SQL Server Database.
I'd like to know why the job raises an event multiple times. If you need more specifics, let me know.
Thanks!