I am writing an app that prints out a (rendered) HTML page to every printer that is installed on the computer the app is running on. I do this by creating a WebBrowser, calling print() on it, and then closing the form. I do this for each printer that is installed on that computer.
My problem is that when I call attempt to close the form, the page does not get printed. Any ideas on how I can make the printing an independent background process, so that I can close the form while it is still printing?
This is the code that I currently have in the form:
public PrintForm()
{
InitializeComponent();
string doc = "C:\\Path\\To\\file.htm";
browser.Url = new Uri(doc);
}
private void PrintForm_Shown(object sender, EventArgs e)
{
Thread t = new Thread(browser.Print);
t.IsBackground = false;
t.Start();
this.Close();
}
I have another class that toggles each of the installed printers as the default printer (the only way to programmatically bypass a print dialogue) and then calls
Applicated.Run(new PrintForm());
Really pretty simply code. Just having a bit of trouble with it.
Yes, this cannot work. The first obstacle you’ll face is that WebBrowser is an apartment threaded COM component. Calling its Print method on a thread doesn’t actually work, COM honors the component’s threading requirements and marshals the call to the thread it was created on, your UI thread.
Your code bombs because the form’s Close() call also disposes all of its child controls. Including the WebBrowser. You can remove it from its Control collection to prevent this from happening, but you still have to call its Dispose() method when it is done printing.
Solving this is not technically impossible, you’d have to create an STA thread that pumps a message loop. Check my code in this thread for the approach.