public static JOB_INFO_2 GetJobInfo(string printerName, int jobId)
        {
            try
            {
                IntPtr _printerHandle = IntPtr.Zero;

                // get printer handle
                _printerHandle = GetPrinterHandle(printerName);
                if (_printerHandle == IntPtr.Zero)
                {
                    return(null);
                }

                //Get the JOB details from GetJob()
                JOB_INFO_2 jobInfo = GetJobInfo2(_printerHandle, jobId);

                // close printer
                bool res = ClosePrinter(_printerHandle);

                // return job info
                return(jobInfo);
            }
            catch (AccessViolationException)
            {
            }
            catch (Exception)
            {
            }

            return(null);
        }
        /// <summary>
        /// Gets job info (2) of the specified printer's job id.
        /// </summary>
        /// <param name="_printerHandle">printer handle</param>
        /// <param name="jobId">job id</param>
        /// <returns>job info (2)</returns>
        private static JOB_INFO_2 GetJobInfo2(IntPtr _printerHandle, int jobId)
        {
            try
            {
                JOB_INFO_2 info         = new JOB_INFO_2();
                Int32      BytesWritten = default(Int32);
                IntPtr     ptBuf        = default(IntPtr);

                //Get the required buffer size
                if (!GetJob(_printerHandle, jobId, 2, ptBuf, 0, ref BytesWritten))
                {
                    if (BytesWritten == 0)
                    {
                        throw new Exception("GetJob for JOB_INFO_2 failed on handle: " + _printerHandle.ToString() + " for job: " + jobId);
                    }
                }

                // Allocate a buffer the right size
                if (BytesWritten > 0)
                {
                    ptBuf = Marshal.AllocHGlobal(BytesWritten * 2);
                }

                if (!GetJob(_printerHandle, jobId, 2, ptBuf, BytesWritten, ref BytesWritten))
                {
                    Marshal.FreeHGlobal(ptBuf);
                    throw new Exception("GetJob for JOB_INFO_2 failed on handle: " + _printerHandle.ToString() + " for job: " + jobId);
                }
                else
                {
                    info = new JOB_INFO_2();
                    Marshal.PtrToStructure(ptBuf, info);

                    //Fill the devmode structure
                    IntPtr ptrDevMode = new IntPtr(info.LPDeviceMode);
                    Marshal.PtrToStructure(ptrDevMode, info.dmOut);
                }

                // Free the allocated memory
                Marshal.FreeHGlobal(ptBuf);

                // return job info
                return(info);
            }
            catch (AccessViolationException)
            {
            }
            catch (Exception)
            {
            }

            return(null);
        }
        /// Methods
        #region Methods

        /// <summary>
        /// Gets the copy count of the specified printer's job id.
        /// </summary>
        /// <param name="printerName">printer name</param>
        /// <param name="jobId">job id</param>
        /// <returns>copy count</returns>
        public static int GetCopyCount(string printerName, int jobId)
        {
            try
            {
                // get job info
                JOB_INFO_2 ji = GetJobInfo(printerName, jobId);

                // get copy count
                int copy = ji.dmOut.dmCopies;

                ji = null;

                return(copy);
            }
            catch
            {
                return(-1);
            }
        }