Printing from webbrowser twice

1

I have problems with COM webbrowser when I try to print through them more than once.
For replicating a problem:

1) Create a new "Windows Forms" project
2) Add COM reference to "Microsoft Internet Controls"
3) Add webbrowser control "webbrowser1" and button "button1" to form (from toolbox)
4) Make sure you have file "c:\index.html"
5) Add this code...

Option Explicit On

Imports System.IO
Imports System.Reflection
Imports System.Diagnostics.Process
Imports System.Runtime.InteropServices
Imports SHDocVw

Public Class Form1
Dim WithEvents p As New PrintHTML
Dim htmlfilename As String

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    p = Nothing
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    htmlfilename = "c:\index.html"
    WebBrowser1.Navigate(htmlfilename)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    p.PrintHTMLDocument(htmlfilename)
End Sub
End Class

Public Class PrintHTML

Dim documentLoaded As Boolean = False
Dim documentPrinted As Boolean = False

Public Sub PrintHTMLDocument(ByVal htmlfilename As String)

    Dim ie As New InternetExplorer
    AddHandler DirectCast(ie, InternetExplorer).PrintTemplateTeardown, AddressOf PrintedCB
    AddHandler DirectCast(ie, InternetExplorer).DocumentComplete, AddressOf LoadedCB

    ie.Navigate(htmlfilename)
    While Not documentLoaded AndAlso ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) <> OLECMDF.OLECMDF_ENABLED
        Application.DoEvents()
        Threading.Thread.Sleep(100)
    End While

    Try
        ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, vbNull, vbNull)
        While Not documentPrinted
            Application.DoEvents()
            Threading.Thread.Sleep(100)
        End While
    Catch ex As Exception
        Debug.Print(ex.Message)
    End Try
End Sub

Private Sub LoadedCB(ByVal obj As Object, ByRef url As Object)
    documentLoaded = True
End Sub

Private Sub PrintedCB(ByVal obj As Object)
    documentPrinted = True
End Sub
End Class

When I Click button1 for first time everiything behaves as expected (printing starts), but when I click to button1 for printing more than once - instead of printing I get error message:

A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in my.exe
Trying to revoke a drop target that has not been registered (Exception from HRESULT: 0x80040100 (DRAGDROP_E_NOTREGISTERED))

What may cause this error and how can I get rid of it to be able to print document more than once with described components?

vb.net
asked on Stack Overflow Oct 4, 2013 by Wine Too • edited Oct 4, 2013 by Soner Gönül

1 Answer

1

It appears you forget to set documentLoaded and documentPrinted back to false before you call Navigate again. They remain being true from the last print-out, and your wait-for-event-in-loop logic doesn't work. I.e., it should be:

documentLoaded = False
documentPrinted = False
ie.Navigate(htmlfilename)
While Not documentLoaded AndAlso ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) <> OLECMDF.OLECMDF_ENABLED
    Application.DoEvents()
    Threading.Thread.Sleep(100)
End While

There is also another issue. Apparently, you do not re-use InternetExplorer object in PrintHTMLDocument and create a new instance every time you print. If for some reason you do not want to re-use it, you should at least be calling ie.Quit at the end of PrintHTMLDocument. Otherwise, you're relying upon .NET garbage collector to free the object (which is an out-of-process COM automation object, each taking some substantial system resources). If you do intend to re-use it, make sure you only add event handlers once.

answered on Stack Overflow Oct 5, 2013 by noseratio • edited Oct 5, 2013 by noseratio

User contributions licensed under CC BY-SA 3.0