locked
How to read Duplex and Pages per Sheet setting from current printjob RRS feed

  • Question

  • Hello.

    My challenge is to intercept all printjobs. Foreach job I want to determine, whether the duplex or the X pages per sheet function was used.

    I’m trying to solve the solution using C# and the .net Framework.
    I already found a couple of solutions to get more general information about the printjob (id, page count, user, color, …) by using WMI and the System.Printing namespace. But I couldn’t retrieve the Duplex or PagerPerSheet information jet.

    My most promising approach was the following (see also my attached code sample):
    - Attach to WMI Creation event for Printjobs to get notified
    - Read jobid from event properties
    - Use System.Printing namespace to get printjob from specific printqueue
    - Pause printjob and try to use its properties

    I already thought to have it solved, when I discovered the PrintTicket (ReachFramework) class attached to the PrintQueue, which offers the properties “Duplexing” and “PagesPerSheet”.
    Unfortunately I had to discover that those Properties – against my expectations – do not represent the state of the printjob I submitted.

    Am I misunderstanding the functionality of the PrintQueue.CurrentJobSettings or do I use it wrong?

    I tried to figure this out for days but starting to spin in circles.
    If anybody could point out my mistake or provide some other solution to intercept this information I would appreciate it very much.
    Thanks in advance,
    Hans-Peter

     

    Sample:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Management;
    using System.Printing;
    using System.Threading;

    namespace PrintJobInterceptor
    {
        //paste this into an console application
        //please add references to ReachFramework, System.Management and System.Printing
        class Program
        {
            static void Main(string[] args)
            {
                // Initialize an event watcher and subscribe to events            
                ManagementEventWatcher watcher = new ManagementEventWatcher();

                string machineName = System.Environment.MachineName;
                string scopeName = String.Format(@"\\{0}\root\CIMV2", machineName);

                watcher.Scope = new ManagementScope(scopeName);
                // attach to creation events of printjobs
                string oQuery = "SELECT * FROM __InstanceCreationEvent WITHIN 0.01 WHERE TargetInstance ISA \"Win32_PrintJob\"";
                watcher.Query = new EventQuery(oQuery);
                watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);

                watcher.Start();

                Console.ReadLine();
            }

            static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
            {
                //some information about printjob can be found in event args
                PrintEventInfo(e);

                int id = GetPrintJobId(e);

                LocalPrintServer s = new LocalPrintServer();

                //XPS printer hardcoded here. Pleade replace with your printer's name.
                PrintQueue q = s.GetPrintQueue("Microsoft XPS Document Writer");

                PrintSystemJobInfo printJob = null;
                try
                {               
                    printJob = q.GetJob(id);
                    //do not enter a breakpoint until the printjob was retrieved from queue. otherwise there will be an excheption in the GetJob method

                    //if you don't pause the job, small jobs will be gone to fast. espacially while debugging.
                    printJob.Pause();

                    //if you don't wait some time and update the info, not all information will be correct (e.g. total page count ,...)
                    Thread.Sleep(1000);
                    printJob.Refresh();
                    printJob.HostingPrintQueue.Refresh();

                    //when i take a look at the various printteckets (especially the current one), i would expect it to hold the correct settings
                    Console.WriteLine("Pages Per Sheet: " + printJob.HostingPrintQueue.CurrentJobSettings.CurrentPrintTicket.PagesPerSheet);
                    //i know xps is only capable of manual duplexing - you can try it with some other printer
                    Console.WriteLine("Duplex: " + printJob.HostingPrintQueue.CurrentJobSettings.CurrentPrintTicket.Duplexing);
                    Console.WriteLine("Copy Count: " + printJob.HostingPrintQueue.CurrentJobSettings.CurrentPrintTicket.CopyCount); 
                 
                    //unfortunately most of the infos are allways null, although i specified them in the print dialog.
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    if (printJob != null)
                        printJob.Resume();
                }
            }

            static void PrintEventInfo(EventArrivedEventArgs e)
            {
                foreach (PropertyData data in e.NewEvent.Properties)
                {
                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine("e.NewEvent.Properties: " + data.Name + " # " + data.Value);


                    if (data.Value is ManagementBaseObject)
                    {
                        foreach (PropertyData qualifier in ((ManagementBaseObject)data.Value).Properties)
                        {
                            Console.WriteLine("- " + qualifier.Name + " # " + qualifier.Value);
                        }
                    }
                    else
                    {
                        int i = 0;
                    }
                }
            }

            static int GetPrintJobId(EventArrivedEventArgs e)
            {
                uint jobId = (uint)((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value).Properties["JobId"].Value;           
                int intId = (int)jobId;
                return intId;
            }
        }
    }

    • Moved by Figo Fei Thursday, April 1, 2010 2:58 AM (From:Common Language Runtime)
    Friday, March 26, 2010 11:07 AM

All replies

  • I think you should probably post this question in Windows Management Forum instead of the CLR forum. It deals more with getting information from the WMI than from the CLR.

     



    Thanks Naveen http://naveensrinivasan.com
    Friday, March 26, 2010 11:16 PM
  • The reason why I didn’t is that the WMI part is only my entry point (my notification) and this works fine. My problem is the usage of the System.Printing namespace and especially the PrintTicket class. That’s why I posted here.

    Thanks anyway for the tip. Maybe I will have a try there, when nobody answers here.

    Saturday, March 27, 2010 12:35 PM