如何使用 C# 打印 PDF
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11579624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to print a PDF with C#
提问by Mx.
I′ve trying to solve this problem for nearly 2 days. There are a lot of more or fewer good solutions on the net, but not a single one fits my task perfectly.
我已经尝试解决这个问题近 2 天了。网络上或多或少有很多好的解决方案,但没有一个完全适合我的任务。
Task:
任务:
- Print a PDF programmatically
- Do it with a fixed printer
- Don′t let the user do more than one Button_Click
- Do it silent - the more, the better
- Do it client side
- 以编程方式打印 PDF
- 用固定打印机做
- 不要让用户做不止一个 Button_Click
- 安静地做——越多越好
- 做客户端
First Solutions:
第一个解决方案:
Do it with a Forms.WebBrowser
用 Forms.WebBrowser 来做
If we have Adobe Reader installed, there is a plugin to show PDF′s in the webbrowser. With this solution we have a nice preview and with webbrowserControlName.Print() we can trigger the control to print its content.
如果我们安装了 Adobe Reader,则有一个插件可以在网络浏览器中显示 PDF。使用这个解决方案,我们有一个很好的预览,使用 webbrowserControlName.Print() 我们可以触发控件打印其内容。
Problem - we still have a PrintDialog.
问题 - 我们还有一个 PrintDialog。
Start the AcroRd32.exe with start arguments
使用启动参数启动 AcroRd32.exe
The following CMD command let us use Adobe Reader to print our PDF.
下面的 CMD 命令让我们使用 Adobe Reader 来打印我们的 PDF。
InsertPathTo..\AcroRd32.exe /t "C:\sample.pdf" "\printerNetwork\printerName"
InsertPathTo..\AcroRd32.exe /t "C:\sample.pdf" "\printerNetwork\printerName"
Problems - we need the absolute path to AcroRd32.exe | there is an Adobe Reader Window opening and it has to be opened until the print task is ready.
问题 - 我们需要 AcroRd32.exe 的绝对路径 | 有一个 Adobe Reader Window 打开,它必须打开,直到打印任务准备就绪。
Use windows presets
使用 Windows 预设
Process process = new Process();
process.StartInfo.FileName = pathToPdf;
process.StartInfo.Verb = "printto";
process.StartInfo.Arguments = "\"" + printerName + "\"";
process.Start();
process.WaitForInputIdle();
process.Kill();
Problem - there is still an Adobe Reader window popping up, but after the printing is done it closes itself usually.
问题 - 仍然会弹出一个 Adobe Reader 窗口,但在打印完成后它通常会自行关闭。
Solution - convince the client to use Foxit Reader (don′t use last two lines of code).
解决方案 - 说服客户使用福昕阅读器(不要使用最后两行代码)。
Convert PDF pages to Drawing.Image
将 PDF 页面转换为 Drawing.Image
I′ve no idea how to do it with code, but when I get this to work the rest is just a piece of cake. Printing.PrintDocument can fulfill all demands.
我不知道如何用代码做到这一点,但是当我让它工作时,其余的只是小菜一碟。Printing.PrintDocument 可以满足所有需求。
Anyone an idea to get some Drawing.Image′s out of those PDF′s or another approach how to do it?
任何人都想从这些 PDF 或其他方法中获取一些 Drawing.Image 的方法吗?
Best Regards, Max
最好的问候,马克斯
回答by Gavin
What about using the PrintDocumentclass?
使用PrintDocument类怎么样?
http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx
http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx
You just need to pass the filename of the file you want to print (based on the example).
您只需要传递要打印的文件的文件名(基于示例)。
HTH
HTH
回答by Turbot
Another approach would to use spooler function in .NET to send the pre-formatted printer data to a printer. But unfortunately you need to work with win32 spooler API
另一种方法是使用 .NET 中的假脱机程序功能将预先格式化的打印机数据发送到打印机。但不幸的是你需要使用 win32 spooler API
you can look at How to send raw data to a printer by using Visual C# .NET
您可以查看如何使用 Visual C# .NET 将原始数据发送到打印机
you only can use this approach when the printer support PDF document natively.
您只能在打印机本身支持 PDF 文档时使用这种方法。
回答by pescolino
You can use ghostscriptto convert PDF into image formats.
您可以使用ghostscript将 PDF 转换为图像格式。
The following example converts a single PDF into a sequence of PNG-Files:
以下示例将单个 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();
}
If you prefer to use Adobe Reader instead you can hide its window:
如果您更喜欢使用 Adobe Reader,则可以隐藏其窗口:
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
回答by yms
If a commercial library is an option, you can try with Amyuni PDF Creator. Net.
如果可以选择商业图书馆,您可以尝试使用Amyuni PDF Creator。网。
Printing directly with the library:
For opening a PDF file and send it to print directly you can use the method IacDocument.Print. The code in C# will look like this:
直接使用库打印:
要打开 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);
Exporting to images (then printing if needed):
Choice 1: You can use the method IacDocument.ExportToJPegfor converting all pages in a PDF to JPG images that you can print or display using Drawing.Image
导出为图像(如果需要,然后打印):
选择 1:您可以使用IacDocument.ExportToJPeg方法将 PDF 中的所有页面转换为 JPG 图像,您可以使用 Drawing.Image 打印或显示这些图像
Choice 2: You can draw each page into a bitmap using the method IacDocument.DrawCurrentPagewith the method System.Drawing.Graphics.FromImage. The code in C# should look like this:
选择 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 );
Disclaimer: I work for Amyuni Technologies
免责声明:我为 Amyuni Technologies 工作
回答by Hinek
I found a slightly different version of your code that uses the printto verb. I didn't try it, but maybe it helps you:
我发现您使用 printto 动词的代码版本略有不同。我没有尝试过,但也许对你有帮助:
回答by Roshana
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();
}
回答by Johan van der Slikke
The most flexible, easiest and best performing method I could find was using GhostScript. It can print to windows printers directly by printer name.
我能找到的最灵活、最简单和性能最好的方法是使用 GhostScript。它可以通过打印机名称直接打印到 windows 打印机。
"C:\Program Files\gs\gs9.07\bin\gswin64c.exe" -dPrinted -dBATCH -dNOPAUSE -sDEVICE=mswinpr2 -dNoCancel -sOutputFile="%printer%printer name" "pdfdocument.pdf"
"C:\Program Files\gs\gs9.07\bin\gswin64c.exe" -dPrinted -dBATCH -dNOPAUSE -sDEVICE=mswinpr2 -dNoCancel -sOutputFile="%printer%打印机名称" " pdfdocument.pdf"
Add these switches to shrink the document to an A4 page.
添加这些开关以将文档缩小到 A4 页面。
-sPAPERSIZE=a4 -dPDFFitPage
-sPAPERSIZE=a4 -dPDFFitPage
回答by Rowan
If you're interested in commercial solutions which do exactly what you require then there are quite a few options. My company provides one of those options in a developer toolkit called Debenu Quick PDF Library.
如果您对完全满足您要求的商业解决方案感兴趣,那么有很多选择。我的公司在名为Debenu Quick PDF Library的开发人员工具包中提供了这些选项之一。
Here is a code sample (key functions are PrintOptionsand PrintDocument):
这是一个代码示例(关键功能是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);
回答by B.K.
I know that the tag has Windows Forms; however, due to the general title, some people might be wondering if they may use that namespace with a WPFapplication -- they may.
我知道标签有Windows Forms; 然而,由于一般的标题,有些人可能想知道他们是否可以在WPF应用程序中使用该名称空间——他们可能会。
Here's code:
这是代码:
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);
}
Now, this namespace must be used with a WPFapplication. It does not play well with ASP.NETor Windows Service. It should not be used with Windows Forms, as it has System.Drawing.Printing. I don't have a single issue with my PDF printing using the above code.
现在,这个命名空间必须与WPF应用程序一起使用。它不适用于ASP.NET或Windows Service。它不应该与 一起使用Windows Forms,因为它已经System.Drawing.Printing。使用上面的代码,我的 PDF 打印没有任何问题。
Note that if your printer does not support Direct Printing for PDF files, this won't work.
请注意,如果您的打印机不支持直接打印 PDF 文件,这将不起作用。
回答by Ian
I tried many things and the one that worked best for me was launching a SumatraPDF from the command line:
我尝试了很多方法,最适合我的方法是从命令行启动 SumatraPDF:
// Launch SumatraPDF Reader to print
String arguments = "-print-to-default -silent \"" + fileName + "\"";
System.Diagnostics.Process.Start("SumatraPDF.exe", arguments);
There are so many advantages to this:
这样做有很多好处:
- SumatraPDF is much much faster than Adobe Acrobat Reader.
- The UI doesn't load. It just prints.
- You can use SumatraPDF as a standalone application so you can include it with your application so you can use your own pa. Note that I did not read the license agreement; you should probably check it out yourself.
- SumatraPDF 比 Adobe Acrobat Reader 快得多。
- 用户界面不加载。它只是打印。
- 您可以将 SumatraPDF 用作独立应用程序,以便将其包含在您的应用程序中,以便您可以使用自己的 pa。请注意,我没有阅读许可协议;你应该自己检查一下。

![C# Dictionary.Add 与 Dictionary[key]=value 的区别](/res/img/loading.gif)