How do I print an HTML document from a web service?

Chris Marasti-Georg picture Chris Marasti-Georg · Aug 1, 2008 · Viewed 15.7k times · Source

I want to print HTML from a C# web service. The web browser control is overkill, and does not function well in a service environment, nor does it function well on a system with very tight security constraints. Is there any sort of free .NET library that will support the printing of a basic HTML page? Here is the code I have so far, which does not run properly.

public void PrintThing(string document)
{
    if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
    {
        Thread thread =
            new Thread((ThreadStart) delegate { PrintDocument(document); });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }
    else
    {
        PrintDocument(document);
    }
}

protected void PrintDocument(string document)
{
    WebBrowser browser = new WebBrowser();
    browser.DocumentText = document;
    while (browser.ReadyState != WebBrowserReadyState.Complete)
    {
        Application.DoEvents();
    }
    browser.Print();
}

This works fine when called from UI-type threads, but nothing happens when called from a service-type thread. Changing Print() to ShowPrintPreviewDialog() yields the following IE script error:

Error: dialogArguments.___IE_PrintType is null or not an object.

URL: res://ieframe.dll/preview.dlg

And a small empty print preview dialog appears.

Answer

ICR picture ICR · Aug 3, 2008

You can print from the command line using the following:

rundll32.exe %WINDIR%\System32\mshtml.dll,PrintHTML "%1"

Where %1 is the file path of the HTML file to be printed.

If you don't need to print from memory (or can afford to write to the disk in a temp file) you can use:

using (Process printProcess = new Process())
{
    string systemPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
    printProcess.StartInfo.FileName = systemPath + @"\rundll32.exe";
    printProcess.StartInfo.Arguments = systemPath + @"\mshtml.dll,PrintHTML """ + fileToPrint + @"""";
    printProcess.Start();
}

N.B. This only works on Windows 2000 and above I think.