Winform 打印PDF順序混亂,獲取打印隊列


工作中PDF打印順序混亂着實讓我疼痛了好久,其實決絕方法非常簡單,但沒有想到這個點子的時候確實讓我走了很多彎路

這里文章寫出來並不是為了炫耀什么,只是覺得發現些好東西就分享出來而已,同時也做個記錄,方便以后查找

開始正文

既然要解決打印順序混亂,那么必須先要實現打印PDF功能,實現PDF打印的方法很多,網上隨便一搜就可以找到,這里我貼上自己的打印方法,其實也是網上找到的,稍稍做了修改

Process proc = new Process();
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.FileName = itemPath;//打印文件路徑(本地完整路徑包括文件名和后綴名)
proc.StartInfo.Verb = "print";
proc.Start();
proc.Close();

這個打印方法非常方便,只要你的電腦安裝了可以閱讀PDF文檔的軟件,都可以打印,不用特定的軟件Adobe Reader、Adobe Acrobat XI等。

但是 當你連續打印多個PDF文檔的時候就出現打印順序混亂的問題,

經調試發現,我發送打印請求的順和打印機接收到的請求的順序是不一致的

我的解決方法是當前一個文檔打印完成后,再發送下一個打印請求,為此我想到如下方法:

就是在上面的進程打印中添加阻塞;proc.WaitForExit();注釋說名的很清楚,等待關聯進程退出

代碼如下:

                    foreach (var itemPath in filePathList)
                    {
                        if (File.Exists(itemPath))
                        {
                            Process proc = new Process();
                            proc.StartInfo.CreateNoWindow = false;
                            proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                            proc.StartInfo.UseShellExecute = true;
                            proc.StartInfo.FileName = itemPath;//打印文件路徑(本地完整路徑包括文件名和后綴名)
                            proc.StartInfo.Verb = "print";
                            proc.Start();
                            proc.WaitForExit();
                            proc.Close();
                        }
                    }

因為PDF打印會關聯你的閱讀PDF文檔軟件,因此沒打印一個PDF文檔就會打開關聯軟件,這樣你必須關掉關聯軟件才會進入下個打印,這樣就很蛋疼了,為此我又做了個線程,這個線程就是實現自動關閉關聯軟件的功能,但是在使用過程中會發現卡主的現象,這樣用戶體驗不好

因此我想到第二種實現方式:在一個打印請求發送給打印機后,就判斷打印機的打印隊列中是存在我發送的打印文檔,如果沒有,則一直等到隊列中已存在打印文檔后,再發送下一個打印請求,要實現這個功能,你必須要先獲取到打印機的打印隊列,

首先要獲得打印機的名稱,我這里使用的是默認打印,為此要獲得默認打印機的名稱(注:必須是本機的,局域網的沒時間研究,等有空了再看看)

        //引入命名空間:using System.Runtime.InteropServices;
        [DllImport("Winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool SetDefaultPrinter(string printerName);

        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int pcchBuffer);

        /// <summary>
        /// 獲取默認打印機 
        /// </summary>
        /// <returns></returns>
        public static string GetDefaultPrinter()
        {
            const int ERROR_FILE_NOT_FOUND = 2;

            const int ERROR_INSUFFICIENT_BUFFER = 122;

            int pcchBuffer = 0;

            if (GetDefaultPrinter(null, ref pcchBuffer))
            {
                return "";
            }

            int lastWin32Error = Marshal.GetLastWin32Error();

            if (lastWin32Error == ERROR_INSUFFICIENT_BUFFER)
            {
                StringBuilder pszBuffer = new StringBuilder(pcchBuffer);
                if (GetDefaultPrinter(pszBuffer, ref pcchBuffer))
                {
                    return pszBuffer.ToString();
                }

                lastWin32Error = Marshal.GetLastWin32Error();
            }
            if (lastWin32Error == ERROR_FILE_NOT_FOUND)
            {
                return "";
            }
            return "";
        }
View Code

然后根據打印機的名稱獲取本地打印機的打印隊列

/// <summary>
        /// 獲取打印機的打印列表
        /// </summary>
        /// <param name="printName">打印機名稱,本地</param>
        /// <returns>返回打印隊列中文檔名稱字符串,多個之間用逗號連接</returns>
        public static string GetPrintJobs(string printName)
        {
            StringBuilder result = new StringBuilder();

            IntPtr handle;
            int FirstJob = 0;
            int NumJobs = 127;
            int pcbNeeded;
            int pcReturned;

            // open printer 
            OpenPrinter(printName, out handle, IntPtr.Zero);

            // get num bytes required, here we assume the maxt job for the printer quest is 128 (0..127) 
            EnumJobs(handle, FirstJob, NumJobs, 1, IntPtr.Zero, 0, out pcbNeeded, out pcReturned);

            // allocate unmanaged memory 
            IntPtr pData = Marshal.AllocHGlobal(pcbNeeded);

            // get structs 
            EnumJobs(handle, FirstJob, NumJobs, 1, pData, pcbNeeded, out pcbNeeded, out pcReturned);

            // create array of managed job structs 
            JOB_INFO_1[] jobs = new JOB_INFO_1[pcReturned];

            // marshal struct to managed 
            int pTemp = pData.ToInt32(); //start pointer 
            for (int i = 0; i < pcReturned; ++i)
            {
                jobs[i] = (JOB_INFO_1)Marshal.PtrToStructure(new IntPtr(pTemp), typeof(JOB_INFO_1));
                result.Append(jobs[i].pDocument);
                result.Append(",");
                pTemp += Marshal.SizeOf(typeof(JOB_INFO_1));
            }

            // cleanup unmanaged memory 
            Marshal.FreeHGlobal(pData);

            // close printer 
            ClosePrinter(handle);

            return result.ToString();
        }
View Code

最后在上面的循環打印的方法里加上判斷,同時去掉proc.WaitForExit();

                    foreach (string pdfPath in paths)
                    {
                        Process proc = new Process();
                        proc.StartInfo.CreateNoWindow = false;
                        proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                        proc.StartInfo.UseShellExecute = true;
                        proc.StartInfo.FileName = pdfPath;
                        proc.StartInfo.Verb = "print";
                        proc.Start();
                        //proc.WaitForExit();
                        proc.Close();
                        string pdfFileName = Path.GetFileName(pdfPath);
                        strPrintName.Append(pdfFileName);
                        strPrintName.Append("\r\n");
                        bool isOk = true;
                        while (isOk)
                        {
                            string strJob =GetPrintJobs(defaultPrintName);
                            if (strJob.Contains(pdfFileName))
                            {
                                isOk = false;
                            }
                        }

                    }

 

另外一種解決方法請看 這里

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM