Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何获得WPF';s DocumentViewer是否释放其对源XPS文档的文件锁定?_Wpf_Xpsdocument_Filelock_Documentviewer - Fatal编程技术网

如何获得WPF';s DocumentViewer是否释放其对源XPS文档的文件锁定?

如何获得WPF';s DocumentViewer是否释放其对源XPS文档的文件锁定?,wpf,xpsdocument,filelock,documentviewer,Wpf,Xpsdocument,Filelock,Documentviewer,在WPF DocumentViewer中显示XPS文件并关闭DocumentViewer实例后,XPS文件被锁定,无法删除。我需要释放XPS文件上的锁,以便删除它,使用相同的名称编写另一个XPS文件,并可以选择在新的DocumentViewer实例中显示该新XPS文件。我需要在同一个应用程序实例中执行此操作-无需关闭应用程序(这是一个打印预览场景) 换句话说,我如何让下面的代码运行而不在“File.Delete(tempXpsFile);”语句中抛出异常 var tempXpsFile = @"

在WPF DocumentViewer中显示XPS文件并关闭DocumentViewer实例后,XPS文件被锁定,无法删除。我需要释放XPS文件上的锁,以便删除它,使用相同的名称编写另一个XPS文件,并可以选择在新的DocumentViewer实例中显示该新XPS文件。我需要在同一个应用程序实例中执行此操作-无需关闭应用程序(这是一个打印预览场景)

换句话说,我如何让下面的代码运行而不在“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();

关闭应用程序确实会释放文件锁,如中所述,但在本场景中这不是一个选项。

您需要关闭System.IO.Packaging.Package,分配给查看器的XpsDocument是从该软件包中打开的。此外,如果希望能够在同一应用程序会话中再次打开同一文件,则必须从PackageStore中删除该包。关闭包将释放文件锁并允许您删除该文件,但在从PackageStore中删除包之前,您将无法重新打开同一文件(或者更准确地说,在同一位置以相同名称打开的任何文件,即使其内容不同)

在问题代码的上下文中,在第一次预览indow.ShowDialog()之后插入以下内容:;在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();

//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在幕后为我做了这件事,然后忘记了清理自己。

不确定这个问题最初是针对.NET的哪个版本提出的,或者这个问题是否在3.x和4.x之间发生了变化,但是从对.NET4.0的一些调查来看,解决方案可能比这简单一些

XpsDocument实现IDisposable,表示使用后需要对其进行Dispose()。问题在于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应该处理的内部包管理内容。

这一次我发现了,我有一个可以下载文档的查看器,一旦设置文档,即使应用了这些更改,它也会失败。当我加载文档时,我正在处理原始文档,这将导致重新加载文档时发布失败。这可以说是最简单的方法!
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();