如何将文件文档发送到打印机并进行打印

本文关键字:打印机 打印 文件 文档 | 更新日期: 2023-09-27 17:57:34

以下是基本前提:

我的用户点击一些小发明,一个PDF文件就会吐到他的桌面上。有没有办法将此文件发送到打印机队列,并将其打印到本地连接的打印机?

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

这个过程他会做很多次。对于教室里的每个学生,他都必须打印一张小成绩单。所以我为每个学生生成一个PDF,我想自动化打印过程,而不是让用户生成PDF,打印,生成PDF,打印机,生成PDF。

关于如何处理这个问题,有什么建议吗?我在Windows XP和Windows窗体上运行。NET 4。

我发现了这个StackOverflow问题,公认的答案是:

创建文件后可以通过命令行打印它们(您可以使用中的命令类系统。的诊断命名空间那)

我该如何做到这一点?

如何将文件文档发送到打印机并进行打印

添加一个新的答案,因为在.net中打印PDF的问题已经存在很长时间了,大多数答案都早于Google Pdfium库,该库现在有.net包装器。对我来说,我自己在研究这个问题,但一直没有发现任何问题,试图找到一些破解的解决方案,比如生成Acrobat或其他PDF阅读器,或者遇到价格昂贵且许可条款不太兼容的商业图书馆。但是GooglePdfium库和PdfiumViewer.net包装器都是开源的,所以对于包括我在内的许多开发人员来说,这是一个很好的解决方案。PdfiumViewer是根据Apache 2.0许可证获得许可的。

你可以在这里获得NuGet包:

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

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

https://github.com/pvginkel/PdfiumViewer

下面是一些简单的代码,可以从PDF文件的文件名中静默打印任意数量的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;
    }
}

您可以告诉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();
}

这会打开AcrobatReader,告诉它将PDF发送到默认打印机,然后在三秒后关闭Acrobat。

如果您愿意在应用程序中附带其他产品,则可以使用GhostScript(免费)或命令行PDF打印机,例如http://www.commandlinepdf.com/(商业)。

注意:示例代码在中打开PDF,是当前注册用于打印PDF的应用程序,它是大多数人机器上的Adobe Acrobat Reader。然而,他们可能使用不同的PDF查看器,如Foxit(http://www.foxitsoftware.com/pdf/reader/)。不过,示例代码应该仍然可以工作。

我知道标签上写着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文件格式的直接打印,那么您就无法使用这种方法了。

以下代码片段改编自Kendall Bennett的代码,用于使用PdfiumViewer库打印pdf文件。主要区别在于使用了Stream而不是文件。

public bool PrintPDF(
            string printer,
            string paperName,
            int copies, Stream stream)
{
    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 = PdfiumViewer.PdfDocument.Load(stream))
        {
            using (var printDocument = document.CreatePrintDocument())
            {
                printDocument.PrinterSettings = printerSettings;
                printDocument.DefaultPageSettings = pageSettings;
                printDocument.PrintController = new StandardPrintController();
                printDocument.Print();
            }
        }
        return true;
    }
    catch (System.Exception e)
    {
        return false;
    }
}

在我的例子中,我使用一个名为PdfSharp的库生成PDF文件,然后将文档保存到流中,如下所示:

PdfDocument pdf = PdfGenerator.GeneratePdf(printRequest.html, PageSize.A4);
pdf.AddPage();
MemoryStream stream = new MemoryStream();
pdf.Save(stream);
MemoryStream stream2 = new MemoryStream(stream.ToArray());

我想指出的一件事可能对其他开发人员有帮助,那就是即使我运行的是Windows 10 64位,我也必须安装32位版本的Pdfium本机DLL才能打印。我在Visual Studio中使用NuGet包管理器安装了以下两个NuGet包:

  • PdfiumViewer
  • PdfiumViewer.Native.x86.v8-xfa

简单的方法:

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

这是一个稍微修改过的解决方案。进程空闲至少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();
}

System.Diagnostics.Process.Start可用于打印文档。将UseShellExecute设置为True,并将谓词设置为"print"。

您可以尝试使用GhostScript,如下所示:

如何使用GhostScript(gswin32c.exe)shell命令在默认网络打印机上打印PDF

我知道Edwin回答了上面的问题,但他只打印了一个文档。我使用此代码来打印给定目录中的所有文件。

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

它本质上循环遍历给定目录变量directory->中的每个文件,对我来说,它是@"C:''Users''Owner''Documents''SalesVaultTesting''",并将这些文件打印到默认打印机

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

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

这很好

您可以使用DevExpress PdfDocumentProcessor.Print(PdfPrinterSettings)方法。

public void Print(string pdfFilePath)
{
      if (!File.Exists(pdfFilePath))
          throw new FileNotFoundException("No such file exists!", pdfFilePath);
      // Create a Pdf Document Processor instance and load a PDF into it.
      PdfDocumentProcessor documentProcessor = new PdfDocumentProcessor();
      documentProcessor.LoadDocument(pdfFilePath);
      if (documentProcessor != null)
      {
          PrinterSettings settings = new PrinterSettings();
          //var paperSizes = settings.PaperSizes.Cast<PaperSize>().ToList();
          //PaperSize sizeCustom = paperSizes.FirstOrDefault<PaperSize>(size => size.Kind == PaperKind.Custom); // finding paper size
          settings.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 600);
          // Print pdf
          documentProcessor.Print(settings);
      }
}
    public static void PrintFileToDefaultPrinter(string FilePath)
    {
        try
        {
            var file = File.ReadAllBytes(FilePath);
            var printQueue = LocalPrintServer.GetDefaultPrintQueue();
            using (var job = printQueue.AddJob())
            using (var stream = job.JobStream)
            {
                stream.Write(file, 0, file.Length);
            }
        }
        catch (Exception)
        {
            throw;
        }
    }