(Print this page)

Setting Windows default printer
Published date: Tuesday, March 1, 2005
On: Moer and Éric Moreau's web site

Have you ever needed to change the default printer from an application? VB.Net lets you change the PrinterName property of the PrinterSettings class without a problem but you will very soon discover that the scope of this modification is limited to the current application only! What if you need to change the default printer as it appears into the Printer and Faxes panel? Read on, you’ll finally find how here!

What inspires me today to write this column is a very recent problem I had at a client site. I have an application written in VB.Net running each morning for over a year that retrieves reports in rtf format from providers and prints them locally. All this runs on the client’s server and was printed on a printer attached to this server. One morning that the job status sent to me by e-mail was indicating that everything went well, the client phoned me asking where her reports where! I first thought she was joking. Then I thought that somebody else had grabbed the reports on the printer for her. We checked the printers’ settings to discover that the default printer was set to “Fax” and that all my reports were queued there! So I have set the default printer back to the HP Laserjet. The next day, she called again. Same story! After some research, I found that each time I was connecting using Terminal Services, the printers’ settings was changing. That was a test made by the sysadmin testing some Terminal Services settings.

Discovering printers

The first class you need to know in the .Net framework when you need to handle printers is the PrinterSettings class from the System.Drawing.Printing namespace.

Typically, you access a PrinterSettings through PrintDocument.PrinterSettings or PageSettings.PrinterSettings properties to modify printer settings. The most common printer setting is PrinterName, which specifies the printer to print to.

This first code snippet lists all available printers to a listbox control (the same devices you see when you open the “Printers and Faxes” panel). This method ends by selecting the current default printer simply by using the PrinterName property from the DefaultPageSettings class.

Private Sub ListAvailablePrinters()
    For Each strPrinterName As String In PrinterSettings.InstalledPrinters
        ListBox1.Items.Add(strPrinterName)
    Next
    'Find the Default printer
    Dim PD As New PrintDocument
    ListBox1.SelectedItem = PD.DefaultPageSettings.PrinterSettings.PrinterName
End Sub

Setting the default printer for the current application

In some circumstances, you will only want to set a printer of particular settings (like paper orientation) for the current application without changing the default values in Windows. To do that, you create an instance of the PrintDocument class, set the properties that describe how to print, and call the Print method to start the printing process.

This is what this code snippet is doing (set a printer and the orientation to landscape):

Dim pd As New PrintDocument
AddHandler pd.PrintPage, AddressOf pd_PrintPage
' Specify the printer to use
pd.PrinterSettings.PrinterName = ListBox1.SelectedItem
' Set the page orientation to landscape.
pd.DefaultPageSettings.Landscape = True
pd.Print()
The complete sample is available from the download link at the end of this column.

Setting the default printer like this does not affect the default printer in Windows. Only documents printed using the PrintDocument class are affected. That method didn’t help me in my story (in which I had a couple a rtf files, some Crystal Reports, and a couple of htm files).

Setting the default printer for Windows

Because the previous method didn’t fix my problem, I have “Googled” to find 3 methods of setting the default printer in Windows from my application. Sadly, none of these 3 methods is 100% pure managed code.

The first method uses Wscript.Network. The second method uses System.Management and InvokeMethod. The third method uses the WriteProfileString API call.

The downloadable demo contains the 3 methods but here, I will only show one method here.

Dim strOldPrinter As String
Dim WshNetwork As Object
Dim pd As New PrintDocument

Try
    strOldPrinter = pd.PrinterSettings.PrinterName
    WshNetwork = Microsoft.VisualBasic.CreateObject("WScript.Network")
    WshNetwork.SetDefaultPrinter(strPrinterName)
    pd.PrinterSettings.PrinterName = strPrinterName 
    If pd.PrinterSettings.IsValid Then 
        Return True
    Else
        WshNetwork.SetDefaultPrinter(strOldPrinter)
        Return False
    End If
Catch exptd As Exception
    WshNetwork.SetDefaultPrinter(strOldPrinter)
    Return False
Finally
    WshNetwork = Nothing
    pd = Nothing
End Try
This is code is pretty straightforward. It creates an instance of Wscript, calls its SetDefaultPrinter method. It also checks to see if it is valid by using the IsValid property after also setting the PrinterName property (the same as previous). If not valid, it reverts to the previous setting.

Figure 1: The test application

Conclusion

Sometime we cannot rely on .Net alone to fulfill our requirements. This does not mean that the task cannot be done. It simply means that we have to dig deeper and use the methods we used long time ago!

Do you care about the sysadmin from the introduction story? Don’t worry form him. He is still one of my friends! He just made my application more robust and gave me a subject to write about.

I hope you appreciated the topic and see you next month.


(Print this page)