工作中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 = ; const int ERROR_INSUFFICIENT_BUFFER = ; int pcchBuffer = ; 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 "";
}

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

/// <summary>
/// 获取打印机的打印列表
/// </summary>
/// <param name="printName">打印机名称,本地</param>
/// <returns>返回打印队列中文档名称字符串,多个之间用逗号连接</returns>
public static string GetPrintJobs(string printName)
{
StringBuilder result = new StringBuilder(); IntPtr handle;
int FirstJob = ;
int NumJobs = ;
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, , IntPtr.Zero, , out pcbNeeded, out pcReturned); // allocate unmanaged memory
IntPtr pData = Marshal.AllocHGlobal(pcbNeeded); // get structs
EnumJobs(handle, FirstJob, NumJobs, , 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 = ; 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();
}

最后在上面的循环打印的方法里加上判断,同时去掉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;
}
} }

另外一种解决方法请看 这里

Winform 打印PDF顺序混乱,获取打印队列的更多相关文章

  1. java从远程服务器获取PDF文件并后台打印(使用pdfFox)

    一.java原生方式打印PDF文件 正反面都打印,还未研究出只打印单面的方法,待解决 public static void printFile(String path) throws Exceptio ...

  2. C# 打印PDF文档的10种方法

    操作PDF文档时,打印是常见的需求之一.针对不同的打印需求,可分多种情况来进行,如设置静默打印.指定打印页码范围和打印纸张大小.双面打印.黑白打印等等.经过测试,下面将对常见的几种PDF打印需求做一些 ...

  3. python 批量打印PDF

    有一批PDF文件,好几百个,每个只打印第2,3页,双面打印. 网上搜索一波,方案如下: 安装Ghostscript,GhostView,使用gsprint命令打印pdf文件. gsprint命令参数说 ...

  4. lodop和c-lodop通过打印状态和任务不在队列获取打印成功

    之前的博文有通过判断pirnt的返回值,判断加入队列算打印成功,建议使用这种简单的判断方法.此外还有其他判断方法,例如通过PRINT_STATUS_OK判断,但是这个状态不是所有打印机能支持这种判断成 ...

  5. C#通过调用WinApi打印PDF文档类,服务器PDF打印、IIS PDF打印

    其他网站下载来的类,可以用于Winform.Asp.Net,用于服务器端PDF或其他文件打印. 直接上代码: using System; using System.Collections.Generi ...

  6. C#使用iTextSharp+ZXing.Net+FreeSpire.PDF生成和打印pdf文档

    项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.Net+FreeSpire.PDF三个类库实现了生成pdf.生成条形码和打印pdf功能. 首先在项 ...

  7. 想请问下PDF双面打印时(打印机自动双面打印)为什么反面那页的内容是倒过来的,应该怎么设置?

    用foxit reader 打印pdf 直接设置为双面打印并且一张2页打印,发现正反面刚好倒着来的,其实说的正反面倒着是从左右翻的角度来讲的,如果上下翻会发现刚好是这个顺序的,这个是要在双面打印设置里 ...

  8. 关于这两天研究Java打印pdf方法的记录

    这两天在研究Java调用打印机打印PDF文件的方法,学到了不少东西,特别来记录一下. 关于Java打印网上最多的而且也是Java正统的打印方法就是使用PrintService,一套比較标准的打印代码例 ...

  9. PDFBox创建并打印PDF文件, 以及缩放问题的处理.

    PDFBox带了一些很方便的API, 可以直接创建 读取 编辑 打印PDF文件. 创建PDF文件 public static byte[] createHelloPDF() { ByteArrayOu ...

随机推荐

  1. C++12!配对

    题目内容:找出输入数据中所有两两相乘的积为12!的对数. 输入描述:输入数据中含有一些整数n(1<=n<232). 输出描述:输出所有两两相乘的积为12!的对数. 题目分析:对于输入的每个 ...

  2. ubuntu打开 txt 文件乱码

    ubuntu12.04 gedit 打开 windows 分区中的 txt 文件乱码,是因为 ubuntu 和 windows 两个系统的编码不同.解决办法:终端里依次输入以下2 条命令即可: 代码: ...

  3. sliding windows (poj 2823) 题解

    [问题描述] 给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表: [样例输入] 8 3 1 3 -1 -3 5 3 6 7 [样例输 ...

  4. Java 第一天

    环境变量设置(以JDK1.7为例) CLASSPATH=.\;C:\Program Files\Java\jdk1.7.0_45\lib\dt.jar;C:\Program Files\Java\jd ...

  5. ASP.NET Core文章汇总

    现有Asp.Net Core 文章资料,2016 3-20月汇总如下 ASP.NET Core 1.0 与 .NET Core 1.0 基础概述 http://www.cnblogs.com/Irvi ...

  6. Linq操作

    Linq使用Group By 1 1.简单形式: var q = from p in db.Products group p by p.CategoryID into g select g; 语句描述 ...

  7. C 构造一个 简单配置文件读取库

    前言 最近看到这篇文章, json引擎性能对比报告 http://www.oschina.net/news/61942/cpp-json-compare?utm_source=tuicool 感觉技术 ...

  8. spring 基本操作总结主要是aop以及依赖注入的基本配置

    一所需架包 spring commom-logging.jar  spring.jar 注解 common-annotation.jar aop面向切面 aspectjrt.jar    aspect ...

  9. hdu 1622 Trees on the level

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1622 小白书上的题... #include<algorithm> #include< ...

  10. Android里面的命名规范

    前前后后接触安卓也有一段时间了,但是对于Android命名规范这块一直没有太注意过.导致有的时候写出来的代码,前后的风格根本不一样,今天在网上查了一下,正好对自己来说可以好好的总结一下. 首先在And ...