6

I have a WebBrowser control in a VB.NET WinForms app. I am able to set the default printer from code and print without prompting the user. However, there is also a print button that shows the PrintDialog. If this action is done first the page will print. Then if I try to programmatically print later (again setting the default printer to some other printer) the it will print to the last printer selected in the PrintDialog box even though I am resetting the default and see the default printer being changed in Windows.

Any ideas?

It works fine unless ShowPrintDialog has a printer chosen first. Once that occurs it seems to always use that printer no matter what I do.

For Each strPrinter In PrinterSettings.InstalledPrinters
            If strPrinter.Contains("My Printer") Then
                wScript.SetDefaultPrinter(strPrinter)
            End If
        Next

        browser.Print()
Developer63
  • 640
  • 7
  • 19
Matt
  • 2,078
  • 2
  • 27
  • 40
  • Could you show some code please, I'm trying to figure out where you are actually calling the 2nd non Print Dialog print – msarchet Apr 01 '10 at 17:15
  • Code added. I am setting the default printer via WMI. After calling SetDefaultPrinter I see the change happen in Printers and Faxes in windows. Yet it will print out to the printer previously selected from ShowPrintDialog call that happened before this code is executed. Prior to this there is a print button with a click event. All that happens there is browser.ShowPrintDialog(). Nothing more. – Matt Apr 01 '10 at 17:35
  • @nobugz: Tried that didn't work – Matt Apr 01 '10 at 17:39

2 Answers2

5

I was able to get the following code to work, without having to open/close a separate form. I've only been looking for this since IE6...

See also these two posts. Programmatically changing the destination printer for a WinForms WebBrowser control

Print html document from Windows Service without print dialog

 // Add references for: COM:  Microsoft Internet Controls; .NET: System.Management.dll
using System;
using System.Reflection;
using System.Threading;
using SHDocVw;
using System.Windows.Controls;
using System.Management;

namespace HTMLPrinting
{
   public class HTMLPrinter
   {
      private bool documentLoaded;
      private bool documentPrinted;
      private string originalDefaultPrinterName;

      private void ie_DocumentComplete(object pDisp, ref object URL)
      {
         documentLoaded = true;
      }

      private void ie_PrintTemplateTeardown(object pDisp)
      {
         documentPrinted = true;
      }

      public void Print(string htmlFilename, string printerName)
      { 
         // Preserve default printer name
         originalDefaultPrinterName = GetDefaultPrinterName();
         // set new default printer
         SetDefaultPrinter(printerName);
         // print to printer
         Print(htmlFilename);
      }

      public void Print(string htmlFilename)
      {
         documentLoaded = false;
         documentPrinted = false;

         InternetExplorer ie = new InternetExplorer();
         ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete);
         ie.PrintTemplateTeardown += new DWebBrowserEvents2_PrintTemplateTeardownEventHandler(ie_PrintTemplateTeardown);

         object missing = Missing.Value;

         ie.Navigate(htmlFilename, ref missing, ref missing, ref missing, ref missing);
         while (!documentLoaded && ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) != OLECMDF.OLECMDF_ENABLED)
            Thread.Sleep(100);

         ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref missing, ref missing);

         // Wait until the IE is done sending to the printer
         while (!documentPrinted)
            Thread.Sleep(100);

         // Remove the event handlers
         ie.DocumentComplete -= ie_DocumentComplete;
         ie.PrintTemplateTeardown -= ie_PrintTemplateTeardown;
         ie.Quit();

         // reset to original default printer if needed
         if (GetDefaultPrinterName() != originalDefaultPrinterName)
         {
            SetDefaultPrinter(originalDefaultPrinterName);
         }
      }

      public static string GetDefaultPrinterName()
      {
         var query = new ObjectQuery("SELECT * FROM Win32_Printer");
         var searcher = new ManagementObjectSearcher(query);

         foreach (ManagementObject mo in searcher.Get())
         {
            if (((bool?)mo["Default"]) ?? false)
            {
               return mo["Name"] as string;
            }
         }

         return null;
      }

      public static bool SetDefaultPrinter(string defaultPrinter)
      {
          using (ManagementObjectSearcher objectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer"))
          {
              using (ManagementObjectCollection objectCollection = objectSearcher.Get())
              {
                  foreach (ManagementObject mo in objectCollection)
                  {
                      if (string.Compare(mo["Name"].ToString(), defaultPrinter, true) == 0)
                      {
                          mo.InvokeMethod("SetDefaultPrinter", null, null);
                          return true;
                      }
                  }
              }
          }
          return true;
      }
   }
}
Community
  • 1
  • 1
Developer63
  • 640
  • 7
  • 19
0

I created a form with nothing on it. The action of launching/closing this form made it go to the right printer... I have no idea why that works, but there must be some function that could be called to simulate whatever action is taking place there.

Matt
  • 2,078
  • 2
  • 27
  • 40