Print Webbrowser Without Previewing I.E. Single Click Print

Print WebBrowser without previewing i.e. single click print

I have a sample console app that prints a set HTML files using WinForms WebBrowser. You can borrow the DoWorkAsync part of it for your printing task in a WinForms application, virtually without any changes:

// by Noseratio - http://stackoverflow.com/users/1768303/noseratio
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConsoleApplicationWebBrowser
{
class Program
{
// Entry Point of the console app
static void Main(string[] args)
{
try
{
// download each page and dump the content
var task = MessageLoopWorker.Run(DoWorkAsync,
"http://www.example.com", "http://www.example.net", "http://www.example.org");
task.Wait();
Console.WriteLine("DoWorkAsync completed.");
}
catch (Exception ex)
{
Console.WriteLine("DoWorkAsync failed: " + ex.Message);
}
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}

// navigate WebBrowser to the list of urls in a loop
static async Task<object> DoWorkAsync(object[] args)
{
Console.WriteLine("Start working.");

var wb = new WebBrowser();
wb.ScriptErrorsSuppressed = true;

if (wb.Document == null && wb.ActiveXInstance == null)
throw new ApplicationException("Unable to initialize the underlying WebBrowserActiveX");

// get the underlying WebBrowser ActiveX object;
// this code depends on SHDocVw.dll COM interop assembly,
// generate SHDocVw.dll: "tlbimp.exe ieframe.dll",
// and add as a reference to the project
var wbax = (SHDocVw.WebBrowser)wb.ActiveXInstance;

TaskCompletionSource<bool> loadedTcs = null;
WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) =>
loadedTcs.TrySetResult(true); // turn event into awaitable task

TaskCompletionSource<bool> printedTcs = null;
SHDocVw.DWebBrowserEvents2_PrintTemplateTeardownEventHandler printTemplateTeardownHandler = (p) =>
printedTcs.TrySetResult(true); // turn event into awaitable task

// navigate to each URL in the list
foreach (var url in args)
{
loadedTcs = new TaskCompletionSource<bool>();
wb.DocumentCompleted += documentCompletedHandler;
try
{
wb.Navigate(url.ToString());
// await for DocumentCompleted
await loadedTcs.Task;
}
finally
{
wb.DocumentCompleted -= documentCompletedHandler;
}

// the DOM is ready,
Console.WriteLine(url.ToString());
Console.WriteLine(wb.Document.Body.OuterHtml);

// print the document
printedTcs = new TaskCompletionSource<bool>();
wbax.PrintTemplateTeardown += printTemplateTeardownHandler;
try
{
wb.Print();
// await for PrintTemplateTeardown - the end of printing
await printedTcs.Task;
}
finally
{
wbax.PrintTemplateTeardown -= printTemplateTeardownHandler;
}
Console.WriteLine(url.ToString() + " printed.");
}

wb.Dispose();
Console.WriteLine("End working.");
return null;
}

}

// a helper class to start the message loop and execute an asynchronous task
public static class MessageLoopWorker
{
public static async Task<object> Run(Func<object[], Task<object>> worker, params object[] args)
{
var tcs = new TaskCompletionSource<object>();

var thread = new Thread(() =>
{
EventHandler idleHandler = null;

idleHandler = async (s, e) =>
{
// handle Application.Idle just once
Application.Idle -= idleHandler;

// return to the message loop
await Task.Yield();

// and continue asynchronously
// propogate the result or exception
try
{
var result = await worker(args);
tcs.SetResult(result);
}
catch (Exception ex)
{
tcs.SetException(ex);
}

// signal to exit the message loop
// Application.Run will exit at this point
Application.ExitThread();
};

// handle Application.Idle just once
// to make sure we're inside the message loop
// and SynchronizationContext has been correctly installed
Application.Idle += idleHandler;
Application.Run();
});

// set STA model for the new thread
thread.SetApartmentState(ApartmentState.STA);

// start the thread and await for the task
thread.Start();
try
{
return await tcs.Task;
}
finally
{
thread.Join();
}
}
}
}

How to skip browser default print preview and print content directly to printer in jquery/javascript?

Browsers will not allow that to happen. You can use the below plugin to provide beautiful previews.

https://github.com/etimbo/jquery-print-preview-plugin

Demo: http://etimbo.github.io/jquery-print-preview-plugin/example/index.html

Close Application after WebBrowser print

PrintTemplateTeardown is what you are looking for.
You can add a reference to SHDocVw. Then you have access to interfaces like IWebBrowser2 and DWebBrowserEvents2_Event.

You can find SHDocVw as "Microsoft Internet Controls" in COM tab of Reference manager window.

You can subscribe DocumentCompleted event to know when the file/url load completed. You can print html document without showing print dialog by calling IWebBrowser2.ExecWB. Also you can subscribe to DWebBrowserEvents2_Event.PrintTemplateTeardown to find out when print completed so you can close the application:

using System;
using System.Windows.Forms;
using SHDocVw;
class Program
{
static System.Windows.Forms.WebBrowser browser;
[STAThread]
static void Main()
{
var fileName = "http://google.com";
browser = new System.Windows.Forms.WebBrowser();
browser.ScriptErrorsSuppressed = true;
browser.DocumentCompleted += browser_DocumentCompleted;
browser.Navigate(fileName);
Application.Run();
}
private static void browser_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
var iwb2 = (IWebBrowser2)browser.ActiveXInstance;
var events = (DWebBrowserEvents2_Event)browser.ActiveXInstance;
events.PrintTemplateTeardown += browser_PrintTemplateTeardown;
var missing = Type.Missing;
iwb2.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
ref missing, ref missing);
}
private static void browser_PrintTemplateTeardown(object pDisp)
{
browser.Dispose();
Application.Exit();
}
}

How to print content of Webrowser in Wpf?

First, you need to get to the underlying WebBrowser ActiveX Control. Here is how it can be done for WPF WebBrowser. Then, you call IWebBrowser2::ExecWB to execute OLECMDID_PRINT or OLECMDID_PRINTPREVIEW commands. Note, these commands are asynchronous. If you need to track when the printing has completed (spooled), check this.

Print directly from browser without print popup window

I couldn't find solution for other
browsers. When I posted this question, IE was on the
higher priority and gladly I found
one for it. If you have a solution
for other browsers (firefox, safari, opera) please do share here.
Thanks.

VBSCRIPT is much more convenient than creating an ActiveX on VB6 or C#/VB.NET:

<script language='VBScript'>
Sub Print()
OLECMDID_PRINT = 6
OLECMDEXECOPT_DONTPROMPTUSER = 2
OLECMDEXECOPT_PROMPTUSER = 1
call WB.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER,1)
End Sub
document.write "<object ID='WB' WIDTH=0 HEIGHT=0 CLASSID='CLSID:8856F961-340A-11D0-A96B-00C04FD705A2'></object>"
</script>

Now, calling:

<a href="javascript:window.print();">Print</a>

will send print without popup print window.

c# WebBrowser Print() Thread in ConsoleApp

I used this post and modified it to suit my requirements. Print WebBrowser without previewing i.e. single click print
Thanks to https://stackoverflow.com/users/1768303/noseratio

C# : How to use WebBrowser and print the html to the console.

OK,

I misunderstood the problem that its a windows application (Winforms)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
PrintHelpPage();
Console.ReadKey();
}

public static void PrintHelpPage()
{
var th = new Thread(() => {
var br = new WebBrowser();
br.DocumentCompleted += PrintDocument;
br.Navigate("http://google.com");
Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}

public static void PrintDocument(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
var browser = sender as WebBrowser;
// Print the document now that it is fully loaded.
browser.Print();

// Dispose the WebBrowser now that the task is complete.
browser.Dispose();
}
}
}

the issue is that a console application would not fire the DocumentCompletedEvent unless you explicitly mark it STAThread as i did in the thread.



Related Topics



Leave a reply



Submit