WPF DocumentViewer doesn't release the XPS file
Asked Answered
P

6

10

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!

Predestine answered 12/11, 2008 at 4:20 Comment(0)
M
2

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

Monstrance answered 12/11, 2008 at 4:20 Comment(2)
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!Predestine
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 #1443107Jollity
J
7

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.

Jollity answered 12/11, 2008 at 4:20 Comment(0)
M
2

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

Monstrance answered 12/11, 2008 at 4:20 Comment(2)
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!Predestine
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 #1443107Jollity
S
0

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.

Slushy answered 12/11, 2008 at 4:20 Comment(0)
P
0

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???

Predestine answered 12/11, 2008 at 4:20 Comment(0)
P
0

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...

Predestine answered 12/11, 2008 at 4:20 Comment(0)
T
0

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)

Toni answered 12/11, 2008 at 4:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.