4

I have the following code to generate a report PDF, upload it and then delete the temporary image used in the generation:

// Generate document and then add a section with an image
var document = new Document {Info = {Title = "Results"}};
var section = document.AddSection();
var logo = section.AddImage(logoPath);

// Render the PDF
const PdfFontEmbedding embedding = PdfFontEmbedding.Always;
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(unicode, embedding);
pdfRenderer.Document = document;
pdfRenderer.RenderDocument(); // This is the line which locks the files

// Save the PDF to a memory stream and upload it to azure blob storage
var reportPath = "";
using (var stream = new MemoryStream())
{
    pdfRenderer.Save(stream, false);
    reportPath = UploadBlob("reports", "Report.pdf", stream);
}

// Delete the local copy of the logo - this is where the exception occurs
Directory.Delete(Directory.GetParent(logoPath).ToString(), true);

When I try to delete the directory of the image, the following exception is raised:

 An exception of type 'System.IO.IOException' occurred in mscorlib.dll but was not handled in user code

 Additional information: The process cannot access the file 'Capture.PNG' because it is being used by another process.

I've debugged through the code to ensure that the file is accessible before the call to pdfRenderer.RenderDocument(), as noted in the code comments.

There are no close or dispose methods for the PdfDocumentRenderer class and it doesn't implement IDisposable so I can't use a using block.

How can I free the lock on the file?

Alasdair Stark
  • 1,227
  • 11
  • 32
  • Have you tried to google first? `BitmapCacheOption.OnLoad` is claimed to be a solution [here](http://forum.pdfsharp.net/viewtopic.php?f=3&t=1832) (FYI: I have no idea what is Migradoc). – Sinatr Nov 05 '14 at 15:21
  • I've Googled it thoroughly, yes. MigraDoc is a library which (I believe) works with PDFSharp to generate PDFs. I got hold of it using the nuget package manager so I don't think I'm able to dive into the source to change any constructors. The changes to Bitmap caching don't help because I have no control over the Bitmap, the AddImage() function only accepts a path to an image so what's going on within that function is very much a black box for me at the moment. – Alasdair Stark Nov 05 '14 at 15:43

2 Answers2

6

I fixed the "BitmapImage lock file" bug modifying PdfSharp.Drawing\XImage.cs as follows: substitute line 114:

  this.wpfImage = new BitmapImage(new Uri(path));  // AGHACK

with

  BitmapImage imgTemp = new BitmapImage();
  imgTemp.BeginInit();
  imgTemp.CacheOption = BitmapCacheOption.OnLoad;
  imgTemp.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
  imgTemp.UriSource = new Uri(path);
  imgTemp.EndInit();
  this.wpfImage = imgTemp;

It worked for me.

Pietro
  • 751
  • 7
  • 22
0

Try using the "PDFsharp-MigraDoc-GDI" package instead of the "PDFsharp-MigraDoc-WPF" package.

BTW: You can download the complete source if you want to make changes in the "black box".
http://pdfsharp.codeplex.com/releases

  • 1
    I can't use the GDI package as my application is running on the Azure cloud and I get the following error: "Internal error. Font data could not retrieved.". It looks like my only solution might be to make my own changes to the source? Why hasn't this been fixed in the GDI version if it's an easy change? – Alasdair Stark Nov 05 '14 at 16:21
  • @Starky: It's not a problem of the GDI build, it's a WPF problem. We haven't published the WPF build on Nuget yet, but we currently plan to release it there later this year - and the fix will be included. For a quick fix, make the changes yourself. – I liked the old Stack Overflow Nov 05 '14 at 17:41