ABCpdf: “Remote process terminated unexpectedly” Exception

Once I got ABCpdf 8 running when invoked from a Windows service, it worked for a long time without any problems:

I split the document, which can become quite large, into its chapters, have each chapter generate the HTML, pass the HTML to ABCpdf, and finally merge the parts using iTextSharp, along with page numbering and header and footer generation.

Until, one day, two chapters consistently raised the exception

System.Exception: Remote process terminated unexpectedly. —> System.Runtime.Serialization.SerializationException:
End of Stream encountered before parsing was completed.
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream,
HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.RpcCaller.Call(MethodBase method, Object[] parameters)
— End of inner exception stack trace —
Server stack trace:
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.RpcCaller.Call(MethodBase method, Object[] parameters)
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.RemoteInstance`1.Invoke(IMessage msg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at WebSupergoo.ABCpdf8.Internal.Gecko.IGeckoWorker.AddImageUrl(String url, Double pageWidthMm, Double pageHeightMm, Byte[] serializedOpts)
at WebSupergoo.ABCpdf8.Internal.Gecko.GeckoCallback.MyCallback(IntPtr closure, IntPtr serializedOpts, UInt32 serializedOptsLen, Double widthInMm, Double heightInMm, String url, UInt32& outNumCommands, IntPtr& outSerializedData, UInt32& outSerializedDataLen)
at WebSupergoo.ABCpdf8.Internal.NDoc.N.AddImageUrlGecko_32(IntPtr doc, String url, Int32 width, IntPtr callback, String& outErr)
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddUrl(Doc doc, String url, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddHtml(Doc doc, String html, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html, Boolean paged, Int32 width, Boolean disableCache)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html)

Teh internets were of no use, unfortunately, and there was no trace of what had happened in the Event Log, so I poked around a bit, and tried to find the intermediate documents or log files hopefully generated by ABCpdf.

I did not find a clue of what exactly had caused the exception, but after deleting the directory

C:\Users\[service account]\AppData\Local\Temp\ABCpdf

PDF generation worked fine again.

Encoding issues with ABCpdf8

I ran across a problem using ABCpdf8 for PDF generation: bullets and the Euro sign are displayed as garbled characters.

What’s going on here?

character name character unicode displayed as UTF-8
bullet U+2022 • 0xE2 0x80 0xA2
Euro sign U+20AC € 0xE2 0x82 0xAC

Since .Net is Unicode-based, the problem cannot be caused by .Net sting handling.

My conclusion is that the Doc.AddImageHtml method creates a temporary file in UTF-8 encoding, and the HTML rendering engine (Gecko in this case) needs to be told about the correct encoding:

doc.AddImageHtml(
  @"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">
  <html xmlns=""http://www.w3.org/1999/xhtml"">
    <head>
      <meta http-equiv=""content-type"" content=""text/xhtml; charset=utf-8"" />
  ... and more HTML content ....
");

In preparing this blog, my assumption was confirmed in the Notes section

ABCpdf saves this HTML into a temporary file and renders the file using a ‘file://’ protocol specifier. So this is a convenience function – it doesn’t offer any performance enhancements.

Using ABCpdf in a Windows Service

One of my long-term projects is a web application which can generate PDF documents on the fly, but bigger PDFs can also be generated offline using a Windows service. Both the web application and the service use the same code base to invoke the ABCpdf library.

Recently, an update of Server 2008 to IE9 forced me to switch to ABCpdf’s Gecko engine, and this switch caused the service, which runs under the Local System account, to fail unexpectedly.

The Event Log contained various error entries:

Source ABCpdf

The following information was included with the event:
Failed to add HTML: Page load timed out.

Source Application Error

Faulting application MyService.exe, version 1.0.0.0, time stamp 0x4f883a56,
faulting module KERNEL32.dll, version 6.0.6002.18005, time stamp 0x49e037dd,
exception code 0xe0434f4d, fault offset 0x0003fbae, process id 0x%9, application start time 0x%10.

Source ASP.Net 2.0.50727.0

An unhandled exception occurred and the process was terminated.

After adding some logging, the following exceptions were reported

Exception: System.Runtime.Serialization.SerializationException

Message: Type ‘WebSupergoo.ABCpdf8.Internal.Spawntaneous.SpawntaneousException’ in Assembly ‘ABCpdf, Version=8.1.0.1, Culture=neutral, PublicKeyToken=a7a0b3f5184f2169’ is not marked as serializable.

StackTrace:    at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeObject(Object obj, MemoryStream stm)
at System.AppDomain.Serialize(Object o)
at System.AppDomain.MarshalObject(Object o)

WebSupergoo.ABCpdf8.Internal.PDFException: Failed to add HTML: Page load timed out.

   at WebSupergoo.ABCpdf8.Internal.Gecko.GeckoCallback.MyCallback(IntPtr closure, IntPtr serializedOpts, UInt32 serializedOptsLen, Double widthInMm, Double heightInMm, String url, UInt32& outNumCommands, IntPtr& outSerializedData, UInt32& outSerializedDataLen)
at WebSupergoo.ABCpdf8.Internal.NDoc.N.AddImageUrlGecko_32(IntPtr doc, String url, Int32 width, IntPtr callback, String& outErr)
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddUrl(Doc doc, String url, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddHtml(Doc doc, String html, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html, Boolean paged, Int32 width, Boolean disableCache)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html)

System.TypeInitializationException: The type initializer for ‘WebSupergoo.ABCpdf8.Internal.Gecko.GeckoCallback’ threw an exception. —> WebSupergoo.ABCpdf8.Internal.Spawntaneous.SpawntaneousException: Failed to generate worker process.

   at WebSupergoo.ABCpdf8.Internal.Spawntaneous.ProcessGenerator.GenerateLocalInvoker(MethodInfo method, String filename, Platform platform, TargetFramework framework)
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.WorkerProcessExe.Init(String filename, Platform platform, TargetFramework framework)
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.WorkerProcessExe..ctor(String filename, Platform platform, TargetFramework framework)
at WebSupergoo.ABCpdf8.Internal.Gecko.GeckoCallback..cctor()
— End of inner exception stack trace —
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddUrl(Doc doc, String url, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddHtml(Doc doc, String html, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html, Boolean paged, Int32 width, Boolean disableCache)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html)

As you can see, the last two exceptions were caused by calling AddImageHtml(), which is the entry point to the invocation of the Gecko rendering engine, therefore my reasoning was that the Gecko engine required something that the MSHTML rendering engine did not need.

I remembered that on IIS, the AppPool’s “Load User Profile” needs to be set, so probably it had something to do with the service running as Local System which does not have a user profile?

As it turns out, setting the service to run under a local user in Control Panel/Administration/Services fixed the problem, and the service was again able to generate PDF files.

Windows Update killed my ABCpdf

An application I develop (dev environment: Win7 Pro, IE9, ASP.Net 3.5) suddenly showed problems running on Windows Server 2008: the web application could not create PDF documents anymore, and

  • The browser only displayed a “Service Unavailable” message
  • The browser user was automatically logged out of the web application
  • The web request did not show in the IIS log
  • No error in the Application events

A process serving application pool ‘MyAppPool’ suffered a fatal communication error with the Windows Process Activation Service. The process id was ‘2688’. The data field contains the error number.

The details tab displayed the following information:

ProcessID 2688
6D000780

Binary data:

In Words

0000: 8007006D

In Bytes

0000: 6D 00 07 80

Teh Internets wanted me to debug IIS and my .Net application with IIS Diagnostics Toolkit, and Debug Diagnostic Tool, and IISState, and awe-inspiring how-to instructions.

Instead, I chose to add logging statements to the code that was affected by the error, and found that cause to be the statement

int theID = doc.AddImageHtml(html);

As it turns out (thank you SO, also here), you need to activate the Gecko engine in ABCpdf to work on (some) IE9 machines (as I said, the code works ok on Win7Pro, and I had recently updated the server):

doc.HtmlOptions.Engine = EngineType.Gecko;

Trying out the Gecko engine, the next result I got was

WebSupergoo.ABCpdf8.Internal.PDFException: ABCpdf cannot detect any printers. Gecko Engine requires a printer installed in the system. Usually, XPS Document Writer would suffice. Try also running the service as an interactive user. —> System.ComponentModel.Win32Exception: The RPC server is unavailable
at System.Drawing.Printing.PrinterSettings.get_InstalledPrinters()
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.get_DefaultPrinter()
— End of inner exception stack trace —
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.get_DefaultPrinter()
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.Preflight(Doc doc)
at WebSupergoo.ABCpdf8.Internal.Gecko.DocAddGecko.AddHtml(Doc doc, String html, Boolean paged, Int32 width, String& err)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html, Boolean paged, Int32 width, Boolean disableCache)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html)

After creating an XPS printer in control panel, the web application was finally able to generate PDF documents again.

According to the ABCpdf support page (6.29), the MSHTML rendering engine should be avoided for future applications:

Unfortunately with the official release of IE9 Microsoft released new documentation which says the IHTMLElementRender::DrawToDC function that was required has been deprecated. This is especially unfortunate given that there is no replacement for this function.

Given that Microsoft appears to be unwilling to support these interfaces we would strongly recommend that on new deployments you consider a move to the new Gecko-based HTML engine available in ABCpdf 8.

Running 32-bit ABCpdf Pro on 64-bit Windows

An application I have been developing needed to add professional generation of PDF documents (read: my home-brew translation of HTML to PDF using iTextSharp did not produce decent results). I decided to use ABCpdf which itself uses the MSHTML engine to render HTML and miraculously converts the result to PDF.

The application consists of a web application and a Windows service which both reference a library implementing the HTML generation and the invocation of ABCpdf.

Development and deployment on 32-bit server were successful, but a production system running Windows Server 64-bit caused several errors:

Exception System.DllNotFoundException

Unable to load DLL ‘ABCpdf8-64.dll’. The specified module could not be found (Exception from HRESULT: 0x8007007E)

This error was caused by the service running in 64-bit mode. (The web application had already been switched to 32-bit only by restricting the application pool to 32-bit execution). After setting the service exe’s “Platform target” property to x86, the error went away.

Exception WebSupergoo.ABCpdf8.Internal.PDFException

Cannot activate MSHtml engine. Please refer to documentation for more information.

The solution for this exception is to set the AppPool’s “Load User Profile” property to true in the Advanced Settings dialog.

After applying these settings, PDF generation also executed successfully on the 64-bit machine.