WPF DocumentViewer не выпускает файл XPS

Я работаю над приложением WPF, которое открывает и отображает документы XPS. Когда приложение закрывается, спецификация приложения должна удалить открытый документ XPS для очистки. Однако при открытии определенного документа XPS приложение выдает исключение, что файл все еще используется, когда оно пытается удалить его. Это немного странно, потому что это происходит только при открытии определенного документа XPS и только когда вы вышли за пределы первой страницы.

Некоторые из кодов, которые я использовал, показаны ниже:

Для открытия документа XPS:

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

Для навигации по документу XPS:

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

Для закрытия объекта DocumentViewer и удаления файла:

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

Все это довольно просто и работает с другими документами, которые мы тестировали. Но с конкретным документом XPS появляется исключение о том, что файл, который нужно удалить, все еще используется.

Что-то не так или отсутствует в моем коде?

Спасибо!

6 ответов

Решение

Сделайте xpsDocument членом, затем не вызывайте close() для него:)

Вам необходимо закрыть System.IO.Packaging.Package, из которого был открыт XpsDocument, назначенный для средства просмотра. Кроме того, если вы хотите снова открыть тот же файл в том же сеансе приложения, вам придется удалить Package из хранилища PackageStore.

Пытаться

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);

Да, я знаю, что вы, вероятно, не открывали XpsDocument с пакетом и, возможно, даже не знаете, что это такое - или заботитесь - но.NET сделал это "для вас" за кулисами и забывает убирать за собой.

Спасибо за ответ!

Это немного низкий уровень, но я буду иметь это в виду, когда у меня кончатся идеи. Во всяком случае, я узнал немного больше об ошибке. В конкретный документ, который вызывает исключение, вставлены изображения. Когда я удаляю изображения, исключение не происходит. Это может быть ошибка DocumentViewer, но я все еще пытаюсь...

Нет, пока что еще ничего.

Просто чтобы перечислить, я попробовал следующие методы, которые потерпели неудачу:

  1. Установите значение null в событии "Закрыто" окна перед удалением файла. Это включает в себя свойство DocumentViewer.Document и объект DocumentViewer.

  2. Использовал ShowDialog(), чтобы открыть окно и затем установить его в нуль. Удаление файла перенесено в событие "Выход" объекта System.Windows.Application, открывающего окно. По-прежнему выдает исключение, что файл используется.

Ошибка DocumentViewer???

Я подозреваю, что вы столкнулись с той же проблемой, что и http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic59281.aspx

Похоже, ошибка в DocumentViewer должна была закрыть вложенные BitmapDecoders при закрытии или загрузить изображение с другой опцией кэширования растрового изображения.

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

Вы можете выяснить, кто держит дескриптор и неуправляемый стек, используя WinDbg

РЕДАКТИРОВАТЬ: И, конечно, вы также можете получить трассировку управляемого стека и осмотреться через расширение SOS ( http://msdn.microsoft.com/en-us/library/bb190764.aspx)

Другие вопросы по тегам