We are getting the following error when printing PDF documents within
an ASP.NET application. If we re-cycle the app domain (clear memory)
the problem goes away for awhile and then returns. Clearing memory
seems to consistently resolve the problem if only temporarily. We are
under the impression something in memory is getting corrupted or some
variable for instance has a bad value.
pdftron.Common.PDFNetException: Unknown exception.
at pdftron.PDF.PDFDraw.DrawInRect(Page page, Graphics gr, Rect
rect)
at DirectWest.Utilities.PDFPrint.PrintPage(Object sender,
PrintPageEventArgs ev) in F:\Inetpub\CustomerInfo2008CC\Project\Support
\DirectWest.Utilities\PDFPrint.vb:line 123
at System.Drawing.Printing.PrintDocument.OnPrintPage
(PrintPageEventArgs e)
at System.Drawing.Printing.PrintDocument._OnPrintPage
(PrintPageEventArgs e)
at System.Drawing.Printing.PrintController.PrintLoop(PrintDocument
document)
at System.Drawing.Printing.PrintController.Print(PrintDocument
document)
at System.Drawing.Printing.PrintDocument.Print()
at DirectWest.Utilities.PDFPrint.Print(String printerName, String
pdfFile, Int16 numberOfCopies, Double dpi, Int32 paperSource, Boolean
autoRotate, Int32 paperSize, Boolean useBuiltInRasterizer) in F:
\Inetpub\CustomerInfo2008CC\Project\Support\DirectWest.Utilities
\PDFPrint.vb:line 64
at DirectWest.CustomerPortfolio.Library.MiniBookExporter.PrintBook
() in F:\Inetpub\CustomerInfo2008CC\Project\Support
\DirectWest.CustomerPortfolio.Library\MiniBook
\MiniBookExporter.vb:line 114
The actual class that does the printing:
Imports System.Configuration
Imports System.Drawing
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices
Imports pdftron
Imports pdftron.SDF
Imports pdftron.PDF
Imports pdftron.Common
Namespace DirectWest.Utilities
Public Class PDFPrint
Private pdfDoc As pdfDoc
Private pdfDraw As pdfDraw
Private pageItr As PageIterator
Private autoRotate As Boolean
Private dpi As Double
Private useBuiltInRasterizer As Boolean
Public Sub Print(ByVal printerName As String, ByVal pdfFile As
String, ByVal numberOfCopies As Short, Optional ByVal dpi As Double =
300, Optional ByVal paperSource As Integer = -1, Optional ByVal
autoRotate As Boolean = True, Optional ByVal paperSize As Integer =
-1, Optional ByVal useBuiltInRasterizer As Boolean = True)
Me.dpi = dpi
Me.autoRotate = autoRotate
Me.useBuiltInRasterizer = useBuiltInRasterizer
PDFNet.Initialize
(System.Configuration.ConfigurationManager.AppSettings
("PDFNETLicense"))
' Create a reference to PDF document
pdfDoc = New PDFDoc(pdfFile)
pdfDoc.InitSecurityHandler()
' Create PDF rasterizer object - PDFDraw
pdfDraw = New PDFDraw
' Create a printer
Dim printer As PrintDocument = New PrintDocument
' Use standard print controller to suppress print progress
dialogue box
printer.PrintController = New StandardPrintController
' Set number of copies
printer.PrinterSettings.Copies = numberOfCopies
' Set printer name
printer.PrinterSettings.PrinterName = printerName
If Not printer.PrinterSettings.IsValid Then
Throw New Exception("An invalid printer was
specified")
End If
' Set the paper source we want to print to
If paperSource <> -1 Then
printer.DefaultPageSettings.PaperSource =
printer.PrinterSettings.PaperSources.Item(paperSource)
End If
' Set the paper size
If paperSize <> -1 Then
printer.DefaultPageSettings.PaperSize =
printer.PrinterSettings.PaperSizes.Item(paperSize)
End If
' Set the PrintPage delegate which will be invoked to
print each page
AddHandler printer.PrintPage, AddressOf PrintPage
AddHandler printer.BeginPrint, AddressOf BeginPrint
' Start printing
printer.Print()
' Close the file
pdfDoc.Close()
End Sub
' Begin printing
Private Sub BeginPrint(ByVal sender As Object, ByVal ev As
PrintEventArgs)
' Start printing from the first page
pageItr = pdfDoc.GetPageIterator()
If useBuiltInRasterizer Then
pdfDraw.SetRasterizerType
(PDFRasterizer.Type.e_BuiltIn)
Else
pdfDraw.SetRasterizerType
(PDFRasterizer.Type.e_GDIPlus)
End If
If dpi <> -1 Then
pdfDraw.SetDPI(dpi)
End If
pdfDraw.SetAntiAliasing(True)
pdfDraw.SetImageSmoothing(True)
End Sub
' Print the page
Private Sub PrintPage(ByVal sender As Object, ByVal ev As
PrintPageEventArgs)
If pageItr.HasNext() Then
Dim gr As Graphics = ev.Graphics
gr.PageUnit = GraphicsUnit.Inch
Dim oPrinterBounds As New PrinterBounds(ev)
Dim pageRect As Rectangle = oPrinterBounds.Bounds
' Define the rectangular area in which the PDF page
will be printed.
Dim left As Double = pageRect.Left / 100.0
Dim right As Double = pageRect.Right / 100.0
Dim top As Double = pageRect.Top / 100.0
Dim bottom As Double = pageRect.Bottom / 100.0
' The above page dimensions are in inches. We need to
convert
' the page dimensions to PDF units (or points). One
point is
' 1/72 of an inch.
Dim rect As Rect = New Rect(left * 72, bottom * 72,
right * 72, top * 72)
If Me.autoRotate Then
Dim box As Rect = pageItr.Current().GetCropBox()
Dim page_rotation As Page.Rotate = pageItr.Current
().GetRotation()
If page_rotation = 90 Or page_rotation = 270 Then
If box.Height() > box.Width() Then
pageItr.Current().SetRotation
(Page.Rotate.e_270)
End If
ElseIf box.Height() < box.Width() Then
pageItr.Current().SetRotation
(Page.Rotate.e_270)
End If
End If
pdfDoc.Lock()
pdfDraw.DrawInRect(pageItr.Current(), gr, rect)
pdfDoc.Unlock()
' Move to the next page
pageItr.Next()
End If
ev.HasMorePages = pageItr.HasNext()
End Sub
End Class
Public Class PrinterBounds
<DllImport("Gdi32", EntryPoint:="GetDeviceCaps",
CharSet:=CharSet.Auto)> _
Public Shared Function GetDeviceCaps(ByVal hDC As IntPtr,
ByVal Index As Integer) As Integer
End Function
Public Bounds As Rectangle
Private Const PHYSICALOFFSETX As Integer = 112
Private Const PHYSICALOFFSETY As Integer = 113
Public Sub New(ByVal ev As PrintPageEventArgs)
Dim dpiX As Single = ev.Graphics.DpiX
Dim dpiY As Single = ev.Graphics.DpiY
Dim hdc As IntPtr = New IntPtr
hdc = ev.Graphics.GetHdc() ' Get handle to device context.
Dim pox As Double = GetDeviceCaps(hdc, PHYSICALOFFSETX)
Dim poy As Double = GetDeviceCaps(hdc, PHYSICALOFFSETY)
ev.Graphics.ReleaseHdc(hdc) ' Release handle to device
context.
Dim HardMarginLeft As Integer = pox * 100.0 / dpiX
Dim HardMarginTop As Integer = pox * 100.0 / dpiY
Bounds = ev.PageBounds
Bounds.Offset(-HardMarginLeft, -HardMarginTop)
End Sub
End Class
End Namespace