2011-05-23 304 views
48

这里的基本前提:如何将文件文件发送到打印机并进行打印?

我的用户点击一些小玩意儿,一个PDF文件被吐出到他的桌面。有没有办法让我将这个文件发送到打印机队列并将其打印到本地连接的打印机上?

string filePath = "filepathisalreadysethere"; 
SendToPrinter(filePath); //Something like this? 

他会做很多次这个过程。对于课堂中的每个学生,他都必须打印一张小小的成绩单。所以我为每个学生生成一个PDF,并且我希望自动化打印过程,而不是让用户生成PDF,打印,生成PDF,打印,生成PDF,打印。

关于如何解决这个问题的任何建议?我在Windows XP与Windows窗体运行.NET 4

我发现这个问题StackOverflow那里接受的答案提示:

一旦你创建你的文件,你 可以通过打印出来一个命令行(你 使用 System.Diagnostics命名空间中发现 的Command类亦可)

我将如何做到这一点?

+0

为什么不合并PDF文档并让用户打印单页,多页文档?似乎不太容易出错,并且很难错过打印其中一个报告(例如,如果其中一个文件发生错误)。 – 2011-05-23 22:35:23

+0

@ 0xA3,我会研究,但现在我需要考虑发送文件到打印机。 – 2011-05-23 22:36:26

回答

53

你可以告诉Acrobat Reader来打印使用文件(如其他人已经这里提到)“打印”动词。您需要在此之后编程方式关闭Acrobat Reader软件,太:

private void SendToPrinter() 
{ 
    ProcessStartInfo info = new ProcessStartInfo(); 
    info.Verb = "print"; 
    info.FileName = @"c:\output.pdf"; 
    info.CreateNoWindow = true; 
    info.WindowStyle = ProcessWindowStyle.Hidden; 

    Process p = new Process(); 
    p.StartInfo = info; 
    p.Start(); 

    p.WaitForInputIdle(); 
    System.Threading.Thread.Sleep(3000); 
    if (false == p.CloseMainWindow()) 
     p.Kill(); 
} 

这将打开Acrobat Reader软件,并告诉它的PDF发送到默认打印机,然后在三秒钟后关闭的Acrobat。

如果您愿意使用您的应用程序发布其他产品,那么您可以使用GhostScript(免费)或命令行PDF打印机,如http://www.commandlinepdf.com/(商业版)。

注:示例代码中打开PDF文件在注册打印PDF文件应用电流,这是Adobe Acrobat Reader软件在大多数人的机器。但是,他们可能会使用不同的PDF查看器,例如Foxit(http://www.foxitsoftware.com/pdf/reader/)。但示例代码仍然可以工作。

+0

为什么此代码在服务器端无法正常工作? – dev 2012-11-06 16:06:07

+1

@Mvcdev代码依赖于:a)在服务器上安装Acrobat(或其他阅读器),以及b)调用交互式应用程序(例如Adobe Acrobat),如果您的代码在用户帐户下运行,则可能不起作用互动。在这种情况下,一个命令行工具是你最好的选择(如上所述www.commandlinepdf.com) – 2012-11-08 14:35:49

+0

其实它正在工作,但是如果我发布该网站,我用iis做的事情并不好。此网站仅适用于内部网络。我有几个步骤。 1)我将应用程序池Asp.NET v4.0标识更改为LocalSystem。 2)我在machine.config文件中的中应用了用户名和密码。 3)我已经使用此网站更改了注册表(http://support.microsoft.com/?kbid=184291)。 N使用你的代码对我来说工作正常。如果在这里出了问题,请指教我? – dev 2012-11-08 16:09:09

3

System.Diagnostics.Process.Start可用于打印文档。将UseShellExecute设置为True并将动词设置为“打印”。

+0

你能详细说明一下吗?我不明白我应该将UseShellExecute设置为true。 – 2011-05-23 22:33:40

+0

'过程。Start'方法可以将一个'ProcessStartInfo'对象作为参数,它具有这些属性。 – 2011-05-23 22:59:12

+0

@Tim Destan:我真的很茫然,这是Verb和UseShellExecute实际上是ProcessStartInfo类的属性吗?你有一些示例代码? – 2011-05-23 23:05:12

9

这是一个稍作修改的解决方案。该进程在闲置至少1秒钟后将被杀死。也许你应该添加一个X秒的时间并从一个单独的线程调用该函数。

private void SendToPrinter() 
{ 
    ProcessStartInfo info = new ProcessStartInfo(); 
    info.Verb = "print"; 
    info.FileName = @"c:\output.pdf"; 
    info.CreateNoWindow = true; 
    info.WindowStyle = ProcessWindowStyle.Hidden; 

    Process p = new Process(); 
    p.StartInfo = info; 
    p.Start(); 

    long ticks = -1; 
    while (ticks != p.TotalProcessorTime.Ticks) 
    { 
    ticks = p.TotalProcessorTime.Ticks; 
    Thread.Sleep(1000); 
    } 

    if (false == p.CloseMainWindow()) 
    p.Kill(); 
} 
24

我所知道的标签说:Windows Forms ...但是,如果有人有兴趣在WPF应用方法,System.Printing的作品就像一个魅力。

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); 
} 

只要记住包括System.Printing参考,如果它尚未包括在内。 现在,这种方法不适用于ASP.NETWindows Service。它不应该与Windows Forms一起使用,因为它有System.Drawing.Printing。使用上面的代码我没有使用我的PDF打印的单个问题。

但是,我应该提到,如果您的打印机不支持直接打印PDF文件格式,那么您使用此方法运气不佳。

+2

这也适用于一个普通的控制台项目。 – Jwosty 2015-08-10 14:47:22

+0

@Jwosty好点。 – 2015-09-25 21:32:26

+0

我试图用我的_HP LaserJet CP1025nw_进行打印,但它不工作。一会儿,它会在状态_spooling_的打印队列中显示打印作业,然后在没有打印的情况下从其中消失 – sohaiby 2017-06-20 09:16:03

1

最简单的办法:

var pi=new ProcessStartInfo("C:\file.docx"); 
pi.UseShellExecute = true; 
pi.Verb = "print"; 
var process = System.Diagnostics.Process.Start(pi); 
4

这是一个迟到的回答,但你也可以使用System.IO命名空间的File.Copy方法顶部的文件发送到打印机:

System.IO.File.Copy(filename, printerName); 

这工作正常

+3

你能否详述一下?我唯一得到的是一个写入硬盘的文件,其名称为'printerName' ... – 2016-05-25 14:44:02

+2

例如:File.Copy(“myFileToPrint.pdf”,“\\ myPrintServerName \ myPrinterName”); – 2017-01-23 23:35:10

2

我知道埃德温在上面回答,但他只打印一个文件。我使用此代码打印来自给定目录的所有文件。

public void PrintAllFiles() 
{ 
    System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(); 
    info.Verb = "print"; 
    System.Diagnostics.Process p = new System.Diagnostics.Process(); 
    //Load Files in Selected Folder 
    string[] allFiles = System.IO.Directory.GetFiles(Directory); 
    foreach (string file in allFiles) 
    { 
     info.FileName = @file; 
     info.CreateNoWindow = true; 
     info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
     p.StartInfo = info; 
     p.Start(); 
    } 
    //p.Kill(); Can Create A Kill Statement Here... but I found I don't need one 
    MessageBox.Show("Print Complete"); 
} 

它essentually通过指定目录变量Directory中的每个文件的循环 - >对我来说是@“C:\用户\用户\文档\ SalesVaultTesting \”和这些文件打印给您的默认打印机

22

为此添加一个新的答案,因为在.net中打印PDF的问题已经存在了很长时间,大多数答案都是在Google Pdfium库之前完成的,该库现在有一个.net包装器。对我来说,我自己正在研究这个问题,并一直空白,试图做出像生成Acrobat或其他PDF阅读器的黑客解决方案,或运行到昂贵且没有非常兼容的许可条款的商业库中。但Google Pdfium库和PdfiumViewer.net包装都是开源的,所以对于很多开发者来说都是一个很好的解决方案,包括我自己在内。 PdfiumViewer获得Apache 2.0许可。

你可以得到NuGet包这里:

https://www.nuget.org/packages/PdfiumViewer/

,你可以找到源代码在这里:

https://github.com/pvginkel/PdfiumViewer

下面是一些简单的代码,会悄悄地打印任何数量的PDF文件副本的文件名。您也可以从流中加载PDF(这是我们通常的做法),并且您可以轻松地查看代码或示例。还有一个WinForm PDF文件视图,因此您也可以将PDF文件渲染到视图中或对其进行打印预览。对于我们来说,我只需要一种方法将PDF文件静默地按需打印到特定的打印机。

public bool PrintPDF(
    string printer, 
    string paperName, 
    string filename, 
    int copies) 
{ 
    try { 
     // Create the printer settings for our printer 
     var printerSettings = new PrinterSettings { 
      PrinterName = printer, 
      Copies = (short)copies, 
     }; 

     // Create our page settings for the paper size selected 
     var pageSettings = new PageSettings(printerSettings) { 
      Margins = new Margins(0, 0, 0, 0), 
     }; 
     foreach (PaperSize paperSize in printerSettings.PaperSizes) { 
      if (paperSize.PaperName == paperName) { 
       pageSettings.PaperSize = paperSize; 
       break; 
      } 
     } 

     // Now print the PDF document 
     using (var document = PdfDocument.Load(filename)) { 
      using (var printDocument = document.CreatePrintDocument()) { 
       printDocument.PrinterSettings = printerSettings; 
       printDocument.DefaultPageSettings = pageSettings; 
       printDocument.PrintController = new StandardPrintController(); 
       printDocument.Print(); 
      } 
     } 
     return true; 
    } catch { 
     return false; 
    } 
} 
+0

这让我在10分钟左右的时间里跑完了。 – 2017-01-27 13:54:23

+0

很好的解决方案,谢谢!还有一个非常好的Google库,它也是开源的,所以它可能会停留更长时间。如果有人对双面打印感兴趣,可以使用'printerSettings.Duplex = Duplex.Vertical'轻松完成此工作,这对我们来说就像是一种魅力。 – Viorel 2017-03-14 09:06:40

+0

这是否也可以在IIS环境中使用?我有通过在IIS中托管的应用程序将pdf(从流生成)传输到网络打印机的场景。我试着用这个代码,我遇到的问题是:1.文档正在排队等待大小为0字节的打印作业队列。 2.文档正在排队到打印作业队列,其所有者名称为machine_name。 – 2017-04-12 07:07:52

相关问题