VB.Net Change Default Printer Settings by code

PNRT
PNRT used Ask the Experts™
on
Hi Experts.    I just deleted a question that I got no response to so I am reposting it in much simpler terms.
When I go in to the properties of my Windows default printer, I can change the default printer preferences such as landscape/portrait etc.

I need to be able to do this through my code.

Changing the print document or page settings is not sufficient.  I need to be able to change the actual default settings as though I had changed the physically.    I have tried many options but none seem to have any effect

Any help appreciated.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Karrtik IyerSoftware Architect

Commented:
To print in landscape mode can you try the below code.
PrintDocument1.DefaultPageSettings.Landscape = True
PrintDocument1.Print()

Open in new window

Else please post the code that you are trying and I can help further.
Karrtik IyerSoftware Architect

Commented:
You  can try this below sample which works. You can give a file path in filepath variable below to see how it prints.
Public Sub Printing()
    Try
        streamToPrint = New StreamReader(filePath)
        Try
            printFont = New Font("Arial", 10)
            Dim pd As New PrintDocument()
            AddHandler pd.PrintPage, AddressOf pd_PrintPage
            pd.PrinterSettings.PrinterName = printer
            ' Set the page orientation to landscape.
            pd.DefaultPageSettings.Landscape = True
            pd.Print()
        Finally
            streamToPrint.Close()
        End Try
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub

Open in new window

Author

Commented:
Hi

Thanks for the replies

Both of these answers refer to the printing of a document.    As I indicated above that's not  what I am trying to do.   I  need to be able to access the default printer preferences and change that

Thanks
Angular Fundamentals

Learn the fundamentals of Angular 2, a JavaScript framework for developing dynamic single page applications.

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ComboBox1.Items.Clear()
        For Each printer As String In Printing.PrinterSettings.InstalledPrinters
            ComboBox1.Items.Add(printer)
        Next printer

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Me.ComboBox1.SelectedItem IsNot Nothing Then
                Shell(String.Format("rundll32 printui.dll,PrintUIEntry /y /n ""{0}""", ComboBox1.SelectedItem))
        End If
    End Sub

Open in new window

Author

Commented:
Hi, many thanks for your reply

Two things
First, this definitely changes the default printer but doesn't allow me to change any preferences as the questions above re landscape/portrait etc

Second, I get an error -
'PInvokeStackImbalance' has detected a problem in 'C:\Users\User\AppData\Local\Temporary Projects\WindowsApplication1\bin\Debug\WindowsApplication1.vshost.exe'.
in the line
 Call SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, "windows")
Karrtik IyerSoftware Architect

Commented:
Apologies I missed your question that you wanted to change the printer settings instead of the settings of particular document, you will have to use win 32 APIs to achieve it. (SetPrinter in winspool.drv).
Please refer the MS knowledge base article230743. The code is VB code, it might need some minor syntactical changes for VB.NET. Let me know if you need help in getting this working in VB.NET
Karrtik IyerSoftware Architect

Commented:
Apologies I missed your question that you wanted to change the printer settings instead of the settings of particular document, you will have to use win 32 APIs to achieve it. (SetPrinter in winspool.drv).
Please refer the MS knowledge base article230743. The code is VB code, it might need some minor syntactical changes for VB.NET. Let me know if you need help in getting this working in VB.NET

Author

Commented:
Hi
I got the errors down from 136 to 23 and then gave up.  I have the feeling that so many changes are being made it will never work.    I'm certain there must be something better in .net.  I'm amazed that there is not something more accessible.   Surely I'm not the only persons who ever required this ability
Karrtik IyerSoftware Architect

Commented:
Give me couple of errors, I have resolved compilation issues. Just need to test it.

Author

Commented:
Thank you for the efforts
Karrtik IyerSoftware Architect

Commented:
Hi PNRT, I am still working on it, please give me some more time to finish this off. Apologies for the delay.
Thanks,
karrtik
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ComboBox1.Items.Clear()
        For Each printer As String In Printing.PrinterSettings.InstalledPrinters
            ComboBox1.Items.Add(printer)
        Next printer
End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Me.ComboBox1.SelectedItem IsNot Nothing Then
                Shell(String.Format("rundll32 printui.dll,PrintUIEntry /y /n ""{0}""", ComboBox1.SelectedItem))
        End If
    End Sub

Open in new window

Author

Commented:
Hi Ali, Many thanks.
Again, this works to change the default printer but doesn't allow me to change the settings.   Am I doing something wrong?
Hi PNRT
You can do every thing you want here, by using this command:
Shell(String.Format("rundll32 printui.dll,PrintUIEntry ...

Rundll32 printui.dll,PrintUIEntry

PrintUI.DLL User's Guide and Reference - Microsoft

Author

Commented:
Hi Ali

From all of the above, the closest I can get with this is to open the printer preferences box.

From this previous Experts Exchange answer it appears that what I want to do is not possible

http://www.experts-exchange.com/questions/21999471/RunDLL-the-Printer-to-SET-Landscape.html

Would you agree?
Karrtik IyerSoftware Architect

Commented:
PNRT, please give me time till tomorrow so that I can say it's not possible, as of now I'm confident.

Author

Commented:
Many thanks Karrtik.   Appreciated
Karrtik IyerSoftware Architect

Commented:
Hi PNRT, I was able to achieve what is mentioned in the below article from Microsoft via VB.NET.
https://support.microsoft.com/en-us/kb/230743230743
1> One approach was to purely convert the above code which was in VB6 to VB.NET and use p invoke.
2> The other was to write a C++/CLI library/layer which can be invoked from VB.NET referencing the C++/CLI library as normal .NET DLL.
I prefer the 2nd one since the 1st One involves lot of type conversions and Marshalling code in VB.NET using PInvoke.
Both work perfectly fine.
However I wanted to ask one more question, this is successfully changing the property from portrait or landscape or another property for any printer configured on that machine where this VB.NET app was executed. So that after this change, any application using the default printer shall print documents as landscape. But this change to printer settings is limited to the machine where this change was done using VB.NET code. This change would not be applicable to other machines where same printer might be configured. Does that work for you?

Author

Commented:
Hi
Many thanks for the effort
Yes that would work correctly.  The printer is local to a single machine and is not shared.
All I need to do is to change the settings of the local default printer from my the code.
Karrtik IyerSoftware Architect

Commented:
Ok, then I shall do some clean up of the code and add some comments and share it with you.
Are both approaches fine with you, or do you want to take my recommended approach (2) or do you want to go with approach 1?

Author

Commented:
If it is possible, I would really prefer both, just in case :-)
Karrtik IyerSoftware Architect

Commented:
Sure, give me some time, I shall give one first with clean up and then share the other, hope that is fine with you. :-)

Author

Commented:
Appreciate the time Karrtik, thanks
Karrtik IyerSoftware Architect

Commented:
Few hours more PNRT, I am almost done, apologies for the delay, was stuck with something else more urgent.
Software Architect
Commented:
Hi PNRT,  
Apologies for the long wait. Here is the first approach (second one in my previous comment) and my suggested/recommended approach my end, which is to invoke a C++/CLI DLL which can contain C++ code to avoid PINVOKE calls and marshaling calls from VB.NET client. From the VB.NET client you shall have a .NET DLL to invoke like shown below. All code have my comments inline.
Please download this zip file from drop box link below, extract, open the solution and run the project, this has been built using VS 2010.
PrinterSettings Test Program
It shall have a text box that shows current default printer and its current orientation settings. You can change the settings and click Apply. Then you can go to your control panel and view the preferences of that printer to see if the changes are applied. It works fine with me. In the text box you can give any other valid printer name and change the orientation settings for the same.
Imports System.Drawing.Printing
Imports PrinterSettingsCLI

Public Class Form1
    Dim defprintername As String
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim allPrinters As System.Drawing.Printing.PrinterSettings.StringCollection = System.Drawing.Printing.PrinterSettings.InstalledPrinters
        For Each eachprinterName As String In allPrinters
            Dim eachprintersetting As Printing.PrinterSettings = New Printing.PrinterSettings()
            eachprintersetting.PrinterName = eachprinterName
            If eachprintersetting.IsDefaultPrinter Then
                defprintername = eachprinterName
                TextBox1.Text = defprintername
                If eachprintersetting.DefaultPageSettings.Landscape Then
                    RadioLandscape.Checked = True
                Else
                    RadioPortrait.Checked = True
                End If
            End If
        Next
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim cliprintersettings As PrinterSettingsCLI.PrinterSettings = New PrinterSettingsCLI.PrinterSettings(TextBox1.Text) 'You can pass any other printer name if you want to 
        Dim retval As Boolean = cliprintersettings.Open()
        Dim orientation As PrinterSettingsCLI.Orientation = orientation.Portrait
        If (retval = True) Then
            If RadioLandscape.Checked Then
                orientation = orientation.Landscape
            Else
                orientation = orientation.Portrait
            End If
            retval = cliprintersettings.SetOrientation(orientation)
        End If
        If (retval = True) Then
            MsgBox("Successful")
            If orientation = orientation.Portrait Then
                RadioPortrait.Checked = True
            Else
                RadioLandscape.Checked = True
            End If
        Else
            MsgBox("UnSuccessful, may be orientation setting is not supported for this printer")
        End If
        retval = cliprintersettings.Close()
        cliprintersettings.Dispose()
        cliprintersettings = Nothing
    End Sub
End Class

Open in new window

Author

Commented:
Hi
Apologies for the late reply, been away for two days
Couldn't get the solution working as the PrinterSettingsCLI.dll is not in the printersettings\PrinterSettings\Debug folder where it was originally, according to the properties.   Also could not find it in the rest of the solution.
Many Thanks
Karrtik IyerSoftware Architect

Commented:
Extract the code, open the solution file (.sln),it shall have two projects. Right click on the solution in solution Explorer and rebuild the entire solution. This should build the dll and exe.
Karrtik IyerSoftware Architect

Commented:
To make things little easier, I have taken the screenshots of the steps to be followed to download the code and building the solution. Please see the attached word document. let me know if you need any further help. Thanks,
karrtik
PNRT_Print_Code_Setup_Steps.docx

Author

Commented:
Works Great.  Many Thanks
Karrtik IyerSoftware Architect

Commented:
You are welcome PNRT :)

Author

Commented:
Hi
Not sure if you will see this karrtik, but when I add am app with this .dll to a clients PC it crashes.  I have downloaded the C++ Redistributable and ran it on the clients PC but still no joy.  Works OK on my laptops with VS on but not on any other machines. Any ideas?

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial