Tuesday, July 17, 2012

Print an XPS Document in VB.Net (and enumerate printers)

Ok, here is the code to enumerate local and network printers and to print an XPS document to the selected printer.  Seems to work just fine, but obviously no fancy options for ya!  Apologies to the many code sample writers I may have lifted a few things from, as I got my head around things. I kept no records, so sorry and thanks!

No fancy formatting of the code, either! Ok, I will make the code a non-black colour.
The XAML code for the WPF form (as if I even know what XAML stands for!):


<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="440" Width="633">
    <Grid>
        <Button x:Name="PrintSimpleTextButton" Content="Print File" HorizontalAlignment="Left" Height="22" Margin="10,95,0,0" VerticalAlignment="Top" Width="70" RenderTransformOrigin="-4.529,-2.864"/>
        <Button x:Name="btnEnumeratePrinters" Content="Enumerate Printers" HorizontalAlignment="Left" Height="22" Margin="10,10,0,0" VerticalAlignment="Top" Width="135"/>
        <ComboBox x:Name="cboPrinters" HorizontalAlignment="Left" Height="22" Margin="10,37,0,0" VerticalAlignment="Top" Width="218"/>
        <TextBox x:Name="txtFilePath" HorizontalAlignment="Left" Height="26" Margin="10,64,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="359"/>


    </Grid>
</Window>

The code for the form


Imports System.Printing
Imports System.IO


Class MainWindow


    Private Sub PrintSimpleTextButton_Click(sender As Object, e As RoutedEventArgs) Handles PrintSimpleTextButton.Click
        If cboPrinters.HasItems Then
            If cboPrinters.SelectedIndex > -1 Then
                Dim strPrinter As String
                strPrinter = cboPrinters.Items(cboPrinters.SelectedIndex).ToString
                If strPrinter.Length > 0 Then
                    Dim nextFile As String = txtFilePath.Text.Trim
                    If File.Exists(nextFile) Then
                        Try
                            Dim printque As PrintQueue
                            Dim printServer As New LocalPrintServer()
                            printque = printServer.GetPrintQueue(strPrinter)
                            ' Print the Xps file while providing XPS validation and progress notifications.
                            Dim xpsPrintJob As PrintSystemJobInfo = printque.AddJob(Path.GetFileName(nextFile), nextFile, False)
                        Catch f As PrintJobException
                            Console.WriteLine(vbLf & vbTab & "{0} could not be added to the print queue.", Path.GetFileName(nextFile))
                            If f.InnerException.Message = "File contains corrupted data." Then
                                Console.WriteLine(vbTab & "It is not a valid XPS file. Use the isXPS Conformance Tool to debug it.")
                            End If
                            Console.WriteLine(vbTab & "Continuing with next XPS file." & vbLf)
                        End Try
                    End If
                End If
            End If
        End If


    End Sub
   
    Private Function fwEnumeratePrinters() As PrintQueueCollection


        ' Specify that the list will contain only the print queues that are installed as local and are shared
        Dim enumerationFlags() As EnumeratedPrintQueueTypes = {EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections}


        Dim printServer As New LocalPrintServer()


        'Use the enumerationFlags to filter out unwanted print queues
        Dim printQueuesOnLocalServer As PrintQueueCollection = printServer.GetPrintQueues(enumerationFlags)


        Return printQueuesOnLocalServer
    End Function ' end:GetPrintTicketFromPrinter()


    Private Sub btnEnumeratePrinters_Click(sender As Object, e As RoutedEventArgs) Handles btnEnumeratePrinters.Click
        Dim pqPrinters As PrintQueueCollection
        cboPrinters.Items.Clear()
        pqPrinters = fwEnumeratePrinters()


        For Each printer As PrintQueue In pqPrinters
            cboPrinters.Items.Add(printer.Name)
        Next


    End Sub


   
    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        txtFilePath.Text = "C:\Users\LIZ\Desktop\First Second Third.xps"
    End Sub
End Class

Wednesday, July 11, 2012

I just want to learn VB.Net. No Biggie.

 Well.  I have programmed in VB from version 3 to version 6, not commercially except for a practice management program I use daily, and a staff rostering program was (is??) used around Australia by a big optical company.  I mainly do front ends to databases (Access, yes, I know, I know; could never get around to or afford, say, SQL Server).  A man needs a hobby, amirite?  A few years ago I reckon I could have done it for a living, now I have been well and truly left behind!

So, I need to get into a new development environment.  I am tempted to go with C#, but I find it difficult to cut myself off from Visual Basic.  I have a simple project that I want written, so I plan to use VB.Net with Visual Studio 2012 to create it.  So, jumping 4 versions of VB in one hit.  OMG!


I want to create the following program:
A Metro-style program in which I can choose already created documents, and send them to a printer.  In addition, I want to select some options (text and images), generate a document, and send a newly generated document to a printer.
Sounds easy.


I initially thought I would just send a PDF to Acrobat with a command to print.  Pfft.  Turns out that is really tricky if you don't want Acrobat to have a UI, and if you don't want to use the default printer.  PDF libraries are really quite expensive, so I shelved that idea after a couple of days of research.


Then I thought, "Wait a minute!  Hasn't Microsoft developed a PDF killer!  I'll do it in XPS format!!!".  LOLZ.


In the last day, I have come to realise that the internetz is a black hole for information about creating XPS documents in VB.NET/WPF.  I can now do my first part, which is load an XPS document and send it to the printer of my choosing, but the second part is really hard to find VB.Net info on.  There is a bit of C# stuff around, but I'm already struggling to learn VB.Net; to convert from C# to VB.Net is one step too far for this VB6 casual programmer!  I really get the feeling that Microsoft has given up on XPS...


So I thought I would record my progress so that others may find a few short cuts.  Of course, there is every possibility that I will fail/give up/not post, but my intentions are good.


If you come across this Blog, and have better solutions, PLEASE add them in comments.  Thanks!


Rene