I'm trying to print the contents of a WPF WebBrowser control so that no print dialog is shown, but am having no luck.
I have tried the following and am sure it did work:
PrintDialog printDialog = new PrintDialog();
printDialog.PrintDocument(((IDocumentPaginatorSource)browser.Document).DocumentPaginator, "My App");
but for some reason, I'm now getting the following exception:
Unable to cast COM object of type 'mshtml.HTMLDocumentClass' to interface type 'System.Windows.Documents.IDocumentPaginatorSource'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{2C0C27DF-282F-3225-ADCD-CEC68F890EEB}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
The only thing I can think has changed on my PC is that I have installed IE8 since I last tried this, but would that really break it?
// Send the Print command to WebBrowser. For this code to work: add the Microsoft.mshtml .NET reference
mshtml.IHTMLDocument2 doc = WebBrowser1.Document as mshtml.IHTMLDocument2;
doc.execCommand("Print", true, null);
Source: http://social.msdn.microsoft.com/Forums/en/wpf/thread/63ae5345-b2ca-45a9-9113-0ddc43e9925b
For silent printing without dialogs, use this code:
private void PrintCurrentPage()
{
// document must be loaded for this to work
IOleServiceProvider sp = WebBrowser1.Document as IOleServiceProvider;
if (sp != null)
{
Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
const int OLECMDID_PRINT = 6;
const int OLECMDEXECOPT_DONTPROMPTUSER = 2;
dynamic wb; // should be of IWebBrowser2 type
sp.QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, out wb);
if (wb != null)
{
// this will send to the default printer
wb.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, null, null);
}
}
}
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IOleServiceProvider
{
[PreserveSig]
int QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
}
To avoid taking a dependency on MSHTML you can simply do:
browser.InvokeScript("execScript", new object[] { "window.print();", "JavaScript" });
I devised the above solution when I was having trouble with a WPF project that was migrated to .Net Core 3 and was using Tony's answer that involves MSHTML reference. Referencing MSHTML in .Net Core is not very straightforward (see this github issue)
User contributions licensed under CC BY-SA 3.0