Winform 列印PDF順序混亂,擷取列印佇列

來源:互聯網
上載者:User

標籤:winform   style   blog   class   code   java   

原文: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;                            }                        }                    }

 

另外一種解決方案請看 這裡

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.