Showing posts with label Libraries. Show all posts
Showing posts with label Libraries. Show all posts

Sunday, November 1, 2009

The "LdrpWalkImportDescriptor() failed to probe XXX.dll for its manifest, ntstatus 0xc0150002" Error and Manifiests

I got this error the other day:

error: LDR: LdrpWalkImportDescriptor() failed to probe QtCored4.dll for its manifest, ntstatus 0xc0150002

I did some googling, and here's what I found out:
  • The error may be a red herring, it's really a SideBySide DLL error. Look in the Event Viewer (see Control Panel, Administrative Tools) for the real error [Mombu, MSDN Social]. It turned out the Microsoft.VC80.DebugCRT DLL could not be found.
  • Usually occurs because of missing DLLs, or DLLs with the incorrect version number (as specified in the DLL's manifest) on the deployment machine.
  • Solutions:

    • Recompile the offending DLL(s) [Nabble, Bytes]
    • Recompile the offending DLL(s), but make sure the DLL project is configured to embed the manifest in the DLL. Have a look at the "dependentAssembly" tag in the generated YourDLLName.intermediate.manifest file. It must be the same as the "dependentAssembly" version in the manifest file generated for your EXE project. Make sure the same service packs are installed (i.e. same msvc) on the machine that built the DLL and the one that built the EXE [Trolltech Lists]
    • Recompile the offending DLL(s), or download and install MSVC Redist SP1 [OpenCV Wiki]

  • FAQ on manifests [CodeGuru]
Here's what worked for me: I checked the manifest file in the DLL that caused the error -- QtCore4d.dll in this example -- and noticed it required the Microsoft.VC80.DebugCRT DLL of a certain version. A colleague of mine compiled the DLL, so I had easy access to the manifest since an "intermediate" copy is stored in the DLL project's build directory. If that wasn't the case, I could use mt.exe from Microsoft to extract it from the DLL. I then inspected the manifest generated by Visual Studio when I compiled my EXE project. It turned out my EXE manifest required a version of the Microsoft.VC80.DebugCRT DLL that was older than that required by the QtCore4d.dll DLL, which means my machine had older DLLs than that required by QtCored4.dll. I simply applied a few Microsoft Visual Studio updates, recompiled my EXE project (not the DLL project), and the newly generated manifest showed the dependent DLL (Microsoft.VC80.DebugCRT) version to be the same as that in the QtCored4.dll manifest. Everything worked fine afterwards.

Wednesday, November 19, 2008

Flying Saucer, XHTML Rendering, and Local XML Entities

I have been using Flying Saucer's (FS) XHTML Renderer [1] for at least 5 months now. It's an excellent library for rendering XHTML for display in Java Swing (using FS's XHTMLPanel) and for converting XHTML content to PDF files (see Generating PDFs for Fun and Profit with Flying Saucer and iText [2]). In my latest project, I create a report in XHTML and use FS to create a PDF version as follows:

String baseUrl ... // root URL for resources
InputStream xhtml = ... // XHTML content
DocumentBuilder builder =
  DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(xhtml);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, baseUrl);
OutputStream os = new FileOutputStream("Out.pdf");
renderer.layout();
renderer.createPDF(os);


One benefit of using this method to create a PDF is that it is much easier to layout the report in XHTML than using a PDF library like iText directly. A second benefit is that I can render the report in two different formats (PDF, XHTML) and render it in a GUI with very little extra work.

Everything worked fine until yesterday.

The problem I ran into today was FS (more correctly the libraries it depends on) would randomly fail with errors such as
java.net.SocketException: Connection reset
and
java.io.IOException: Server returned HTTP response code: 503 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd

After help from the very responsive FS users group [3], the problem was that my XML document builder would sometimes fail when accessing the web to resolve XML entities, even though I was connected to the Internet. I was able to fix the problem by adding one line of code to configure the entity resolver to use XML entities on the class path (and conveniently packaged in FS's core-renderer.jar).

String baseUrl ...
InputStream xhtml = ...
DocumentBuilder builder =
  DocumentBuilderFactory.newInstance().newDocumentBuilder();
// Use FS's local cached XML entities so we don't
// have to hit the web.
builder.setEntityResolver(FSEntityResolver.instance());
Document doc = builder.parse(xhtml);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, baseUrl);
OutputStream os = new FileOutputStream("Out.pdf");
renderer.layout();
renderer.createPDF(os);


The moral of the story is that some thought should always be given to how you configure your XML parsers to resolve entities. In many cases it makes more sense to use a local store, not a default remote site such as www.w3.org. This is especially important if the application doing the parsing may run on computers not connected to the Internet. This applies to FS and other libraries that depend on parsing XML.

References

[1] The Flying Saucer Project, 2008
[2] Joshua Marinacci, Generating PDFs for Fun and Profit with Flying Saucer and iText, 2007
[3] Flying Saucer User Mailing List, 2008