如何使用 C# 打印 PDF
Posted
技术标签:
【中文标题】如何使用 C# 打印 PDF【英文标题】:How to print a PDF with C# 【发布时间】:2012-07-19 17:54:50 【问题描述】:我试图解决这个问题将近 2 天。网上有很多或多或少的好解决方案,但没有一个完全适合我的任务。
任务:
以编程方式打印 PDF 使用固定打印机进行操作 不要让用户执行多次 Button_Click 保持沉默 - 越多越好 做客户端第一个解决方案:
使用 Forms.WebBrowser 进行操作
如果我们安装了 Adobe Reader,有一个插件可以在网络浏览器中显示 PDF。有了这个解决方案,我们有一个很好的预览,并且有了 webbrowserControlName.Print(),我们可以触发控件来打印它的内容。
问题 - 我们还有一个 PrintDialog。
使用启动参数启动 AcroRd32.exe
下面的 CMD 命令让我们使用 Adobe Reader 来打印我们的 PDF。
InsertPathTo..\AcroRd32.exe /t "C:\sample.pdf" "\printerNetwork\printerName"
问题 - 我们需要 AcroRd32.exe 的绝对路径 |有一个 Adobe Reader 窗口打开,必须打开它,直到打印任务准备好。
使用 Windows 预设
Process process = new Process();
process.StartInfo.FileName = pathToPdf;
process.StartInfo.Verb = "printto";
process.StartInfo.Arguments = "\"" + printerName + "\"";
process.Start();
process.WaitForInputIdle();
process.Kill();
问题 - 仍然会弹出一个 Adobe Reader 窗口,但打印完成后它通常会自行关闭。
解决方案 - 说服客户使用 Foxit Reader(不要使用最后两行代码)。
将 PDF 页面转换为 Drawing.Image
我不知道如何使用代码来完成,但是当我让它工作时,剩下的只是小菜一碟。 Printing.PrintDocument 可以满足所有需求。
有人想从那些 PDF 中获取一些 Drawing.Image 或其他方法吗?
最好的问候, 最大
【问题讨论】:
试试Print existing PDF (or other files) in C#。 要获取 Drawing.Image,您可以查看此示例:ghostscriptnet.codeplex.com/SourceControl/… 这是几年后的事了……你能弄清楚Drawing.Image
路线吗?
@B.K.可悲的是没有 - 但今天可能有更好的方法
@Max 我已经找了好几个月了,但我还没有找到一个不涉及在客户端机器上安装东西的解决方案......在我的情况下这不是一个选项.
【参考方案1】:
我能找到的最灵活、最简单、性能最好的方法是使用 GhostScript。它可以通过打印机名称直接打印到windows打印机。
"C:\Program Files\gs\gs9.07\bin\gswin64c.exe" -dPrinted -dBATCH -dNOPAUSE -sDEVICE=mswinpr2 -dNoCancel -sOutputFile="%printer%打印机名称 " "pdfdocument.pdf"
添加这些开关可将文档缩小为 A4 页面。
-sPAPERSIZE=a4 -dPDFFitPage
【讨论】:
我建议为此使用 Ghostscript 包装器。比如:ghostscriptnet.codeplex.com @HABJAN 感谢您的建议,看起来确实很有用。 我使用了 Ghostscript.NET(可通过 NuGet 获得)。当我尝试最新版本的ghostscript(9.18)时,我收到了内存访问异常。我卸载了 9.18,发现 Ghostscript.NET 上次构建之前的最新版本是 9.15。一旦我安装了它,一切似乎都开始工作了。您可以在downloads.ghostscript.com/public 获取先前版本的 ghostscript Ghostscript 的 mswinpr2 质量相当差 - 它将输入的 PDF 文件转换为光栅文件并打印出来。更好的方法是使用 3rd 方组件或尝试自己实现某些东西,尤其是打印机众所周知的 PDF/PS。在这里我找到了简单而漂亮的命令行工具effisoft.pl/rawfileprinter【参考方案2】:另一种方法是使用 .NET 中的假脱机功能将预先格式化的打印机数据发送到打印机。但不幸的是,您需要使用 win32 spooler API
你可以看看How to send raw data to a printer by using Visual C# .NET
只有当打印机本身支持 PDF 文档时,才能使用此方法。
【讨论】:
我在回答中没有提到的好点。我会更新答案,但可能是 OP 需要的? 好点,但我不能确定所有打印机都支持它。即使目前所有的打印机都支持它,如果他们购买没有此功能的其他产品也会有问题。 链接现在转到 404。【参考方案3】:如果可以选择商业库,您可以尝试使用Amyuni PDF Creator. Net.
直接使用库打印: 要打开 PDF 文件并直接发送打印,您可以使用方法IacDocument.Print。 C# 中的代码将如下所示:
// Open PDF document from file<br>
FileStream file1 = new FileStream ("test.pdf", FileMode.Open, FileAccess.Read);
IacDocument doc1 = new IacDocument (null);
doc1.Open (file1, "" );
// print document to a specified printer with no prompt
doc1.Print ("My Laser Printer", false);
导出为图像(然后在需要时打印): 选择 1:您可以使用方法IacDocument.ExportToJPeg 将 PDF 中的所有页面转换为可以使用 Drawing.Image 打印或显示的 JPG 图像
选择 2:您可以使用方法 IacDocument.DrawCurrentPage 和方法 System.Drawing.Graphics.FromImage 将每个页面绘制成位图。 C# 中的代码应如下所示:
FileStream myFile = new FileStream ("test.pdf", FileMode.Open, FileAccess.Read);
IacDocument doc = new IacDocument(null);
doc.Open(myFile);
doc.CurrentPage = 1;
Image img = new Bitmap(100,100);
Graphics gph = Graphics.FromImage(img);
IntPtr hdc = gph.GetHDC();
doc.DrawCurrentPage(hdc, false);
gph.ReleaseHdc( hdc );
免责声明:我为 Amyuni Technologies 工作
【讨论】:
【参考方案4】:您可以使用ghostscript 将PDF 转换为图像格式。
以下示例将单个 PDF 转换为 PNG 文件序列:
private static void ExecuteGhostscript(string input, string tempDirectory)
// %d will be replaced by ghostscript with a number for each page
string filename = Path.GetFileNameWithoutExtension(input) + "-%d.png";
string output = Path.Combine(tempDirectory, filename);
Process ghostscript = new Process();
ghostscript.StartInfo.FileName = _pathToGhostscript;
ghostscript.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
ghostscript.StartInfo.Arguments = string.Format(
"-dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -r300 -sOutputFile=\"0\" \"1\"", output, input);
ghostscript.Start();
ghostscript.WaitForExit();
如果您更喜欢使用 Adobe Reader,您可以隐藏它的窗口:
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
【讨论】:
【参考方案5】:我发现使用 printto 动词的代码版本略有不同。我没试过,但也许对你有帮助:
http://vbcity.com/forums/t/149141.aspx
【讨论】:
好的,刚刚看到这行不通:Adobe 的论坛说,新版本的 Adobe Reader 不允许您打印“静默”、“出于安全原因”(当然,Adobe)...总会有一个窗口。【参考方案6】:我知道标签有Windows Forms
;但是,由于通用标题,有些人可能想知道他们是否可以将该命名空间与WPF
应用程序一起使用——他们可以。
代码如下:
var file = File.ReadAllBytes(pdfFilePath);
var printQueue = LocalPrintServer.GetDefaultPrintQueue();
using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
stream.Write(file, 0, file.Length);
现在,这个命名空间必须与WPF
应用程序一起使用。它不适用于ASP.NET
或Windows Service
。它不应该与Windows Forms
一起使用,因为它有System.Drawing.Printing
。使用上述代码打印 PDF 时没有任何问题。
请注意,如果您的打印机不支持直接打印 PDF 文件,这将不起作用。
【讨论】:
【参考方案7】:我尝试了很多方法,最适合我的方法是从命令行启动 SumatraPDF:
// Launch SumatraPDF Reader to print
String arguments = "-print-to-default -silent \"" + fileName + "\"";
System.Diagnostics.Process.Start("SumatraPDF.exe", arguments);
这样做有很多好处:
-
SumatraPDF 比 Adobe Acrobat Reader 快得多。
UI 未加载。它只是打印。
您可以将 SumatraPDF 作为一个独立的应用程序使用,这样您就可以将它包含在您的应用程序中,这样您就可以使用自己的 pa。请注意,我没有阅读许可协议;你应该自己去看看。
【讨论】:
【参考方案8】:我公司提供 Docotic.Pdf 库,可以render and print PDF documents。链接后面的文章包含有关以下主题的详细信息:
直接在 Windows 窗体或 WPF 应用程序中打印 PDF 通过中间图像打印 PDF 在图形上渲染 PDF也有示例代码的链接。
我在公司工作,所以请阅读这篇文章并自己尝试建议的解决方案。
【讨论】:
【参考方案9】:使用PrintDocument
类怎么样?
http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx
您只需要传递您要打印的文件的文件名(基于示例)。
HTH
【讨论】:
正如我所描述的,这可以与 Drawing.Image 一起使用。它不适用于 .pdf。检查 pd_PrintPage(object sender, PrintPageEventArgs ev) 事件。 .txt 文件中的每一行都转换为打印输出。 请参阅daniweb.com/software-development/csharp/threads/90272/… 以获得可能的解决方案。【参考方案10】: Process proc = new Process();
proc.StartInfo.FileName = @"C:\Program Files\Adobe\Acrobat 7.0\Reader\AcroRd32.exe";
proc.StartInfo.Arguments = @"/p /h C:\Documents and Settings\brendal\Desktop\Test.pdf";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
for (int i = 0; i < 5; i++)
if (!proc.HasExited)
proc.Refresh();
Thread.Sleep(2000);
else
break;
if (!proc.HasExited)
proc.CloseMainWindow();
【讨论】:
【参考方案11】:如果您对完全符合您要求的商业解决方案感兴趣,那么有很多选择。我的公司在名为 Debenu Quick PDF Library 的开发人员工具包中提供了其中一个选项。
这是一个代码示例(关键函数是PrintOptions和PrintDocument):
/* Print a document */
// Load a local sample file from the input folder
DPL.LoadFromFile("Test.pdf", "");
// Configure print options
iPrintOptions = DPL.PrintOptions(0, 0, "Printing Sample")
// Print the current document to the default
// printing using the options as configured above.
// You can also specify the specific printer.
DPL.PrintDocument(DPL.GetDefaultPrinterName(), 1, 1, iPrintOptions);
【讨论】:
【参考方案12】:截至July 2018
,OP 仍然没有答案。没有免费的方法可以 1) 为 2) 闭源项目静默打印您的 pdf。
1) 您当然可以使用 Adobe Acrobat 或 Foxit Reader 等进程
2) 免费解决方案具有 GPL(GNU 通用公共许可证)。这意味着如果将软件提供给公司以外的任何人,即使是免费的,您也必须开放源代码。
正如 OP 所说,如果您可以将 PDF 转换为 Drawing.Image,则可以使用 .NET 方法打印它。遗憾的是,执行此操作的软件还需要付费或 GPL。
【讨论】:
以上是关于如何使用 C# 打印 PDF的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Windows 10 附带的 Microsoft Print To PDF 打印机以编程方式打印到 PDF 文件而不提示 C# 中的文件名