博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Winform 打印PDF顺序混乱,获取打印队列
阅读量:6283 次
发布时间:2019-06-22

本文共 5971 字,大约阅读时间需要 19 分钟。

工作中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);        ///         /// 获取默认打印机         ///         /// 
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

然后根据打印机的名称获取本地打印机的打印队列

///         /// 获取打印机的打印列表        ///         /// 打印机名称,本地        /// 
返回打印队列中文档名称字符串,多个之间用逗号连接
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;                            }                        }                    }

 

另外一种解决方法请看 

 

 

 

转载于:https://www.cnblogs.com/springSky/p/3227285.html

你可能感兴趣的文章
生成器
查看>>
spark监控入门
查看>>
mysql加锁处理分析
查看>>
ceph0.94安装
查看>>
css里各个元素的书写顺序
查看>>
【JOISC2018|2019】【20190622】minerals
查看>>
笔试算法题(20):寻找丑数 & 打印1到N位的所有的数
查看>>
朋友们请珍重自己的身体
查看>>
Android Handler机制简介
查看>>
2012/10/8——假期结束了
查看>>
RIYUXX
查看>>
finalize和System.gc()的区别
查看>>
几个数组去重的方法
查看>>
微软指定推荐沃通WoSign EV代码签名证书
查看>>
架构师速成-如何高效编程 for java
查看>>
struts2上传文件
查看>>
敏捷软件开发宣言和敏捷宣言遵循的12个原则
查看>>
前端日志
查看>>
重复数据删除和SSD的互补方法
查看>>
Using Regular Expressions in Python
查看>>