Print to XPS without a Save As dialog

Bernoulli Lizard picture Bernoulli Lizard · Feb 20, 2014 · Viewed 7.4k times · Source

How can I save an xps file by printing to a virtual printer without using the Save File As dialog? When I call the print method, a dialog automatically pops up asking the user to specify the file name and path. This only works when creating brand new files; it throws an error 'you do not have permission to write to that file...' if I attempt to overwrite an existing file. Anyways, I want the user to be able to specify the file name in my own dialog, not the one that is autamatically called by the printDocument's Print method.

Public Event PrintPage As System.Drawing.Printing.PrintPageEventHandler
Private WithEvents Doc As New Printing.PrintDocument

Public Sub SaveXPSFile()
    Doc.PrinterSettings.PrinterName = "Microsoft XPS Document Writer"
    Doc.PrinterSettings.PrintFileName = "C:\Users\POConnell\Documents\t.xps"
    Doc.Print()
    Doc.Dispose()
End Sub

Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles Doc.PrintPage
   'drawing commands go here
End sub

Answer

Matt Anderson picture Matt Anderson · May 28, 2014

It's a couple of months late, but here we go.

2 questions, two answers.

Question 1: How can I save an xps file by printing to a virtual printer without using the Save File As dialog?

Answer 1: You were close. I think you're looking for

Doc.DefaultPageSettings.PrinterSettings.PrintToFile = True Doc.DefaultPageSettings.PrinterSettings.PrintFileName = "C:\Users\POConnell\Documents\t.xps"

Here is my implementation: (Legal paper size, landscape mode)

        Using prn As New PrintDocument
            With prn
                .PrinterSettings.PrinterName = "Microsoft XPS Document Writer"
                AddHandler .PrintPage, _
                   AddressOf Me.PrintPageHandler
                .DefaultPageSettings.Landscape = landscape
                .DefaultPageSettings.PaperSize = New PaperSize("Legal", 850, 1400)
                If My.Computer.FileSystem.FileExists("C:\temp\Log.oxps") Then My.Computer.FileSystem.DeleteFile("C:\temp\Log.oxps")
                .DefaultPageSettings.PrinterSettings.PrintToFile = True
                .DefaultPageSettings.PrinterSettings.PrintFileName = "C:\temp\Log.oxps"
                .Print()
                RemoveHandler .PrintPage, _
                   AddressOf Me.PrintPageHandler
            End With
        End Using

As you can see, I use the oxps file format, but it should still work just the same for you.

Question 2: it throws an error 'you do not have permission to write to that file...' if I attempt to overwrite an existing file.

Answer 2: Check if the file already exists prior to printing the file, and delete it if it does. Of course it will fail attempting to create a file that already exists.

For some reason using My.Computer.FileSystem.DeleteFile is faster than the traditional Kill() and System.IO.File.Delete, which both require the thread to sleep for ~1-200ms prior to recreating the file, or else a different access denied error will occur.

Hopefully this helps someone in the future!