【问题标题】:Printing an external PDF document in VB.net在 VB.net 中打印外部 PDF 文档
【发布时间】:2015-01-14 06:06:55
【问题描述】:

我知道以前有人问过这个问题,但我的情况有点不稳定。

基本上,我正在尝试打印使用以前的 Windows 窗体生成的 PDF 文件。我可以找到文件没有问题,我使用了以下代码,我在 MSDN 的帮助论坛上找到了:

Dim p As New System.Diagnostics.ProcessStartInfo()
p.Verb = "print"
p.WindowStyle = ProcessWindowStyle.Hidden
p.FileName = "C:\534679.pdf"   'This is the file name
p.UseShellExecute = True
System.Diagnostics.Process.Start(p)

到目前为止一切顺利,但每次我按下按钮运行此代码时,它都会要求我将其保存为 PDF 文件,如下所示:

我还尝试将 PrintDialog 添加到 Windows 窗体,让它弹出,我可以从那里选择我想使用的打印机,但即使选择了打印机,它仍然要求我打印到 PDF 文档而是。

我做错了什么?

【问题讨论】:

  • 发生这种情况是因为您的默认打印机是 Foxit Reader PDF 打印机,它不打印任何内容,而是创建一个 PDF 文件。尝试将真实打印机设置为默认值。

标签: vb.net printing


【解决方案1】:

要使用VB.Net 打印大量PDF 文档,您可以使用LVBPrint 并通过command line 运行它:

http://www.lvbprint.de/html/gsbatchprint1.html

例如:

C:\temp\gsbatchprint64\gsbatchprintc.exe -P \\server\printer -N A3 -O Port -F C:\temp\gsbatchprint64\Test*.pdf -I Tray3

我在我的应用程序中使用以下函数:

    ' print a pdf with lvbrint
    Private Function UseLvbPrint(ByVal oPrinter As tb_Printer, fileName As String, portrait As Boolean, sTray As String) As String

        Dim lvbArguments As String
        Dim lvbProcessInfo As ProcessStartInfo
        Dim lvbProcess As Process

        Try

            Dim sPrinterName As String

                If portrait Then
                    lvbArguments = String.Format(" -P ""{0}"" -O Port -N A4 -F ""{1}"" -I ""{2}"" ", sPrinterName, fileName, sTray)
                Else
                    lvbArguments = String.Format(" -P ""{0}"" -O Land -N A4 -F ""{1}"" -I ""{2}"" ", sPrinterName, fileName, sTray)
                End If

            lvbProcessInfo = New ProcessStartInfo()
            lvbProcessInfo.WindowStyle = ProcessWindowStyle.Hidden

            ' location of gsbatchprintc.exe
            lvbProcessInfo.FileName = LvbLocation 
            lvbProcessInfo.Arguments = lvbArguments

            lvbProcessInfo.UseShellExecute = False

            lvbProcessInfo.RedirectStandardOutput = True
            lvbProcessInfo.RedirectStandardError = True


            lvbProcessInfo.CreateNoWindow = False

            lvbProcess = Process.Start(lvbProcessInfo)

            '
            ' Read in all the text from the process with the StreamReader.
            '
            Using reader As StreamReader = lvbProcess.StandardOutput
                Dim result As String = reader.ReadToEnd()
                WriteLog(result)
            End Using

            Using readerErr As StreamReader = lvbProcess.StandardError
                Dim resultErr As String = readerErr.ReadToEnd()
                If resultErr.Trim() > "" Then
                    WriteLog(resultErr)

                    lvbProcess.Close()
                    Return resultErr
                End If
            End Using

            If lvbProcess.HasExited = False Then
                lvbProcess.WaitForExit(3000)
            End If

            lvbProcess.Close()

            Return ""

        Catch ex As Exception
            Return ex.Message 
        End Try
    End Function

我不鼓励使用 AcrRd32.exe,因为它不适用于大量打印。

【讨论】:

    【解决方案2】:

    我使用此代码在 VB NET 上打印我的 PDF 文件:

        Dim PrintPDF As New ProcessStartInfo
        PrintPDF.UseShellExecute = True
        PrintPDF.Verb = "print"
        PrintPDF.WindowStyle = ProcessWindowStyle.Hidden
        PrintPDF.FileName = dirName & fileName 'fileName is a string parameter
        Process.Start(PrintPDF)
    

    执行此操作时,进程会保持打开状态,并带有一个 adobe 阅读器窗口,用户必须手动关闭该窗口。我想避免用户的交互,只是想让他们得到他们的文件。所以,我添加了几行代码来杀死进程:

        Private Sub killProcess(ByVal processName As String)
        Dim procesos As Process()
        procesos = Process.GetProcessesByName(processName) 'I used "AcroRd32" as parameter
    
            If procesos.Length > 0 Then
                For i = procesos.Length - 1 To 0 Step -1
                    procesos(i).Kill()
                Next
            End If
    
     End Sub
    

    如果您将 kill process 方法放在 print 方法之后,您将不会打印您的文档(我想这是因为进程在发送到打印机之前被杀死)。因此,在这两种方法之间,我添加了这一行:

       Threading.Thread.Sleep(10000) ' 10000 is the milisecs after the next code line is executed
    

    这样我的代码就可以按我的意愿工作了。希望对你有帮助!

    【讨论】:

      【解决方案3】:

      此代码将帮助您在特定打印机上打印。

      示例使用 ProcessStartInfo 和特定打印机打印文件您可以更改要在流程中使用的打印机。

      如果打印过程在 10 秒后仍未完成,我们将终止打印过程。

      'Declare a printerSettings
      Dim defaultPrinterSetting As System.Drawing.Printing.PrinterSettings = Nothing
      
      
      Private Sub cmdPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPrint.Click
      
          Try
      
              dim fileName As String = "C:\534679.pdf"
      
      
              'Get de the default printer in the system
              defaultPrinterSetting = DocumentPrinter.GetDefaultPrinterSetting
      
      
              'uncomment if you want to change the default printer before print
              'DocumentPrinter.ChangePrinterSettings(defaultPrinterSetting)
      
      
              'print your file 
               If PrintFile(fileName, defaultPrinterSetting) then
                   msgbox ("your print file success message")
               else
                   msgbox ("your print file failed message")
      
               end if
      
          Catch ex As Exception
              mssbox(ex.Message.toString)
          End Try
      
      End Sub
      
      
      Public NotInheritable Class DocumentPrinter
      
          Shared Sub New()
      
          End Sub
      
          Public Shared Function PrintFile(ByVal fileName As String, printerSetting As System.Drawing.Printing.PrinterSettings) As Boolean
      
              Dim printProcess As System.Diagnostics.Process = Nothing
              Dim printed As Boolean = False
      
              Try
      
                  If PrinterSetting IsNot Nothing Then
      
      
                      Dim startInfo As New ProcessStartInfo()
      
                      startInfo.Verb = "Print"
                      startInfo.Arguments = defaultPrinterSetting.PrinterName     ' <----printer to use---- 
                      startInfo.FileName = fileName 
                      startInfo.UseShellExecute = True
                      startInfo.CreateNoWindow = True
                      startInfo.WindowStyle = ProcessWindowStyle.Hidden
      
                      Using print As System.Diagnostics.Process = Process.Start(startInfo)
      
                         'Close the application after X milliseconds with WaitForExit(X)   
      
                          print.WaitForExit(10000)
      
                          If print.HasExited = False Then
      
                              If print.CloseMainWindow() Then
                                  printed = True
                              Else
                                  printed = True
                              End If
      
                          Else
                              printed = True
      
                          End If
      
                          print.Close()
      
                      End Using
      
      
              Else
                  Throw New Exception("Printers not found in the system...")
              End If
      
      
              Catch ex As Exception
                  Throw
              End Try
      
              Return printed
      
          End Function
      
      
          ''' <summary>
          ''' Change the default printer using a print dialog Box
          ''' </summary>
          ''' <param name="defaultPrinterSetting"></param>
          ''' <remarks></remarks>
          Public Shared Sub ChangePrinterSettings(ByRef defaultPrinterSetting As System.Drawing.Printing.PrinterSettings)
      
              Dim printDialogBox As New PrintDialog
      
              If printDialogBox.ShowDialog = Windows.Forms.DialogResult.OK Then
      
                  If printDialogBox.PrinterSettings.IsValid Then
                      defaultPrinterSetting = printDialogBox.PrinterSettings
                  End If
      
              End If
      
          End Sub
      
      
      
          ''' <summary>
          ''' Get the default printer settings in the system
          ''' </summary>
          ''' <returns></returns>
          ''' <remarks></remarks>
          Public Shared Function GetDefaultPrinterSetting() As System.Drawing.Printing.PrinterSettings
      
              Dim defaultPrinterSetting As System.Drawing.Printing.PrinterSettings = Nothing
      
              For Each printer As String In System.Drawing.Printing.PrinterSettings.InstalledPrinters
      
      
                  defaultPrinterSetting = New System.Drawing.Printing.PrinterSettings
                  defaultPrinterSetting.PrinterName = printer
      
                  If defaultPrinterSetting.IsDefaultPrinter Then
                      Return defaultPrinterSetting
                  End If
      
              Next
      
              Return defaultPrinterSetting
      
          End Function
      
      End Class
      

      【讨论】:

      • 不幸的是,该代码的当前形式无法正常工作。
      【解决方案4】:

      首先,为了能够选择打印机,您必须使用 PrintDialogPrintDocument 将要打印的图形发送到所选打印机。

      Imports System.Drawing.Printing
      
          Private WithEvents p_Document As PrintDocument = Nothing
      
          Private Sub SelectPrinterThenPrint()
              Dim PrintersDialog As New PrintDialog()
      
              If PrintersDialog.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then
                  Try
                      p_Document = New PrintDocument()
                      PrintersDialog.Document = p_Document
                      AddHandler p_Document.PrintPage, AddressOf HandleOnPrintPage
      
                  Catch CurrentException As Exception
      
                  End Try
              End If
          End Sub
      
          Private Sub HandleOnPrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs) Handles p_Document.PrintPage
              Dim MorePagesPending As Boolean = False
      
              'e.Graphics.Draw...(....)
              'e.Graphics.DrawString(....)
              ' Draw everything...
      
              If MorePagesPending Then
                  e.HasMorePages = True
              Else
                  e.HasMorePages = False
              End If
          End Sub
      

      这就是我正在做的,因为我通常要打印自定义对象。


      但要打印 PDF 文件,您必须了解 PDF 对 dotNet 意味着绝对没有。与位图 (.bmp) 或 Ping 图像 (.png) 等常见图像不同,dotNet 似乎没有任何用于读取、显示和打印 PDF 文件的内置解析器/解码器。

      因此,您必须使用第三方应用程序、第三方或您自己的自定义 PDF 解析器/布局生成器才能能够将要打印的页面发送到您的打印机。

      这就是您无法使用“打印”命令启动 Acrobat Reader 的隐藏(不可见)进程的原因。您将无法选择打印机,而是直接使用默认打印机!

      但是,您可以启动 Acrobat Reader 进程来打开文件,然后在 在 Acrobat Reader 中进行打印操作(选择打印机)(您现在处于 dotNet 编码之外)


      您也可以通过打开 Acrobat Reader 来选择另一台默认打印机,然后在 actual working printer 上打印一个空白页。这应该取消选择您的 FoxIt 以支持实际的打印机..

      【讨论】:

        猜你喜欢
        • 2020-06-10
        • 2017-11-26
        • 2016-10-09
        • 1970-01-01
        • 1970-01-01
        • 2011-09-20
        • 1970-01-01
        • 1970-01-01
        • 2012-05-24
        相关资源
        最近更新 更多