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?
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.
User contributions licensed under CC BY-SA 3.0