views:

2463

answers:

8

hello!

I am working on a WPF application that opens and displays XPS documents. When the application closes, the specification is the application should delete the opened XPS document for clean up. However, when opening a certain XPS document, the application throws an exception that the file is still in use when it tries to delete it. It is a little weird because it only happens when opening a particular XPS document and only when you have moved beyond the first page.

Some of the codes I used are shown below:

For opening the XPS Document:

DocumentViewer m_documentViewer = new DocumentViewer();
XpsDocument m_xpsDocument = new XpsDocument(xpsfilename, fileaccess);
m_documentViewer.Document = m_xpsDocument.GetFixedDocumentSequence();
m_xpsDocument.Close();

For navigating the XPS document:

m_documentViewer.FirstPage();
m_documentViewer.LastPage();
m_documentViewer.PreviousPage();
m_documentViewer.NextPage();

For closing the DocumentViewer object and deleting the file:

m_documentViewer.Document = null;
m_documentViewer = null;
File.Delete(xpsfilename);

It's all pretty basic and it works with the other documents that we tested. But with the particular XPS document, an exception pops up saying that the file to be deleted is still being used.

Is there something wrong or missing from my code?

Thanks!

A: 

http://blogs.msdn.com/junfeng/archive/2008/04/21/use-htrace-to-debug-handle-leak.aspx

You can figure out who holds the handle and the unmanaged stack using WinDbg

EDIT: And of course, you can also get the managed stack trace and poke around via the SOS extension (http://msdn.microsoft.com/en-us/library/bb190764.aspx)

Paul Betts
A: 

Thanks for the reply!

It's a little low-level but I'll keep it in mind when I run out of ideas. Anyway, I found out a little more about the bug. The particular document that causes the exception have images inserted in them. When I remove the images, the exception doesn't happen. This could be a DocumentViewer bug maybe but I'm still trying...

A: 

Hi,

I am also getting the same problem. When I display the XPS file which contains the image data, then the file is not released by the Document Viewer. Did you find any work around for this?

thanks, Jigar Chhadwa.

A: 

Hello!

Nope, so far still nothing.

Just to enumerate, I've tried the following methods that failed:

  1. Set everything to null in the "Closed" event of the window before deleting the file. This includes the DocumentViewer.Document property and the DocumentViewer object.

  2. Used ShowDialog() to open the window and set it to null afterwards. Moved the deletion of the file to the "Exit" event of the System.Windows.Application object that is opening the window. Still throws the exception that the file is being used.

DocumentViewer bug???

+1  A: 

Make the xpsDocument a member, then don't call close() on it :)

moogs
Hey this one worked! I just left the XpsDocument object open and only called XpsDocument.Close() during exit and I was able to delete the file. Thanks moogs!
This works only if you can close your application to release the lock. If you need the lock released while your application remains open you will need to see my answer below or in http://stackoverflow.com/questions/1442607/how-do-i-get-wpfs-documentviewer-to-release-its-file-lock-on-the-source-xps-docu
Tim Erickson
A: 

I suspect you are running into the same issue as http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic59281.aspx

Sounds like a bug in DocumentViewer it should have disposed of nested BitmapDecoders on close or loaded the image with a different bitmap caching option.

Ifeanyi Echeruo
A: 

Can anyone make Moogs reply make any sense. Member of what, the local Moose Lodge?

Thanks!

pedrodems
+1  A: 

You need to close the System.IO.Packaging.Package from which the XpsDocument assigned to the viewer was opened. Further, if you want to be able to open the same file again within the same application session, you will have to remove the Package from the PackageStore.

Try

var myXpsFile = @"c:\path\to\My XPS File.xps";
var myXpsDocument = new XpsDocument(myXpsFile);
MyDocumentViewer.Document = myXpsDocument;

//open MyDocumentViwer's Window and then close it
//NOTE: at this point your DocumentViewer still has a lock on your XPS file
//even if you Close() it
//but we need to do something else instead

//Get the Uri from which the system opened the XpsPackage and so your XpsDocument
var myXpsUri = myXpsDocument.Uri; //should point to the same file as myXpsFile

//Get the XpsPackage itself
var theXpsPackage = System.IO.Packaging.PackageStore.GetPackage(myXpsUri);

//THIS IS THE KEY!!!! close it and make it let go of it's file locks
theXpsPackage.Close();

File.Delete(myXpsFile); //this should work now

//if you don't remove the package from the PackageStore, you won't be able to
//re-open the same file again later (due to System.IO.Packaging's Package store/caching
//rather than because of any file locks)
System.IO.Packaging.PackageStore.RemovePackage(myXpsUri);

Yes, I know you probably didn't open the XpsDocument with a Package and might not even know what one is - or care - but .NET did it "for" you behind the scenes and forgets to clean up after itself.

Tim Erickson