WPF의 DocumentViewer가 소스 XPS 문서에서 파일 잠금을 해제하도록하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/1442607

문제

WPF DocumentViewer에 XPS 파일을 표시하고 DocumentViewer 인스턴스를 닫은 후 XPS 파일이 잠겨 있으며 삭제할 수 없습니다. XPS 파일에서 잠금을 릴리스하여 삭제하고 동일한 이름의 다른 이름을 쓰고 새 XPS 파일을 새 DocumentViewer 인스턴스에 선택적으로 표시 할 수 있습니다. 앱을 닫지 않고도 동일한 앱 인스턴스 에서이 작업을 수행해야합니다 (이것은 인쇄 미리보기 시나리오입니다).

다시 말해, "file.delete (tempxpsfile)"에서 예외를 던지지 않고 다음 코드를 실행하는 방법; 성명?

var tempXpsFile = @"c:\path\to\Temporary.xps";

var previewWindow = new Window();
var docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

GenerateXpsFile(tempXpsFile);

var xpsDocument = new XpsDocument(tempXpsFile);

previewWindow.ShowDialog();

File.Delete(tempXpsFile);  //this will throw an exception due to a file lock on tempXpsFile

GenerateXpsFile(tempXpsFile); //assume this generates a different file
//otherwise the scenario doesn't make sense as we could just skip the above delete
//and this statement and re-use the same file

previewWindow = new Window();
docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

previewWindow.ShowDialog();

앱을 닫으면 언급 된대로 파일 잠금이 해제됩니다. WPF DocumentViewer는 XPS 파일을 해제하지 않습니다, 그러나이 시나리오에서는 옵션이 아닙니다.

도움이 되었습니까?

해결책

뷰어에 할당 된 XPSDocument가 열린 System.io.packaging.package를 닫아야합니다. 또한 동일한 응용 프로그램 세션 내에서 동일한 파일을 다시 열 수 있으려면 Packagestore에서 패키지를 제거해야합니다. 패키지를 닫으면 파일 잠금이 해제되고 파일을 삭제할 수 있지만 동일한 파일 (또는 더 정확하게는 동일한 위치에있는 모든 파일이 동일한 이름으로 해당 파일이있는 경우에도 더 정확하게는 재개 할 수 없습니다. 다른 컨텐츠) Packagestore에서 패키지를 제거 할 때까지.

질문의 코드의 맥락에서 첫 번째 previewwindow.showdialog () 다음에 다음을 삽입하십시오. file.delete (tempxpsfile) 앞에;

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

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

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

따라서 질문에 제시된 고정 코드 세그먼트는 다음과 같습니다.

var tempXpsFile = @"c:\path\to\Temporary.xps";

var previewWindow = new Window();
var docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

GenerateXpsFile(tempXpsFile);

var xpsDocument = new XpsDocument(tempXpsFile);

previewWindow.ShowDialog();

//BEGIN NEW CODE
var myXpsUri = xpsDocument.Uri; //should point to the same file as tempXpsFile
var theXpsPackage = System.IO.Packaging.PackageStore.GetPackage(myXpsUri);
theXpsPackage.Close();
System.IO.Packaging.PackageStore.RemovePackage(myXpsUri);
//END NEW CODE

File.Delete(tempXpsFile);  //this will succeed now

GenerateXpsFile(tempXpsFile);

previewWindow = new Window();
docViewer = new DocumentViewer();
previewWindow.Content = docViewer;

previewWindow.ShowDialog();

그렇습니다. 패키지로 XPSDocument를 열지 않았다는 것을 알고 있습니다. -.NET가 "ME Behin

다른 팁

.NET의 .NET 버전이 원래 3.X와 4.X 사이에 변경되었는지 여부에 대해 원래 질문을했는지 확실하지 않지만 .NET 4.0에 대한 일부 조사에서 솔루션이 상당히 상당히 나타날 수 있습니다. 이것보다 간단합니다.

XPSDocument 구현 Idisposable은 사용 후 () D를 처리해야 함을 나타냅니다. 주름은 idisposable.dispose ()가 숨겨져서 직접 호출 할 수 없도록 구현된다는 것입니다. 대신 Close ()를 호출해야합니다. dotpeek을 사용하여 xpsdocument.dispose ()를 분석합니다.

  • xpsdocument.close () 호출 xpsdocument.dispose ()
  • xpsdocument.dispose () 호출 xpsmanager.close ()
  • xpsmanager.close () 호출 xpsmanager.removepackagereference ()
  • xpsmanager.removepackagereference () 호출 packagestore.removepackage () 및 package.close ()

따라서 무언가를 놓치지 않는 한 XPSDocument를 처리 해야하는 내부 패키지 관리 작업을 파헤칠 필요없이 XPSDocument (어쨌든해야 할 일)를 Close ()에 닫는다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top