WPF DocumentViewer doesn't release the XPS file

bjutus picture bjutus · Nov 12, 2008 · Viewed 11k times · Source

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!

Answer

Tim Erickson picture Tim Erickson · Sep 2, 2009

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.