.NET中的IMAPI2 MsftFileSystemImage在创建ISO时不释放文件

我成功创建了iso映像,但是在调用此Create方法返回后,我尝试删除rootFolderPath中的文件时出现’文件正在使用’IO错误。 我错过了Marshal.ReleaseComObject调用吗?

谢谢,

CW

///  /// Create iso image from rootFolderPath and write to isoImageFilePath. Does not include the actual rootFolder itself ///  public void Create() { IFileSystemImage ifsi = new MsftFileSystemImage(); try { ifsi.ChooseImageDefaultsForMediaType(IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK); ifsi.FileSystemsToCreate = FsiFileSystems.FsiFileSystemJoliet | FsiFileSystems.FsiFileSystemISO9660; ifsi.VolumeName = this.volumeName; ifsi.Root.AddTree(rootFolderPath, false);//use a valid folder //this will implement the Write method for the formatter IStream imagestream = ifsi.CreateResultImage().ImageStream; if (imagestream != null) { System.Runtime.InteropServices.ComTypes.STATSTG stat; imagestream.Stat(out stat, 0x01); IStream newStream; if (0 == SHCreateStreamOnFile(isoImageFilepath, 0x00001001, out newStream) && newStream != null) { IntPtr inBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(long))); IntPtr outBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(long))); try { imagestream.CopyTo(newStream, stat.cbSize, inBytes, outBytes); Marshal.ReleaseComObject(imagestream); imagestream = null; newStream.Commit(0); } finally { Marshal.ReleaseComObject(newStream); Marshal.FreeHGlobal(inBytes); Marshal.FreeHGlobal(outBytes); if (imagestream != null) Marshal.ReleaseComObject(imagestream); } } } } finally { Marshal.ReleaseComObject(ifsi); } } 

锁定大文件肯定存在问题。 在网上挖掘会产生以下几点:

因此,在所有这些消化后,我得到了一个解决方案:在写入之后,迭代文件系统映像根并释放任何流数据。

多会话光盘存在一些问题 – 由于现有文件是导入的(通过ImportFileSystem),所有文件都会被检查锁定,这可能需要一些时间,并且每个未在当前会话中写入的内容都会引发COMException 。 通过一些努力,我确信可以缓存AddTree之前和之后的文件系统之间的差异,并且只检查那些文件。

无论如何……在调用Write之后,我们调用ReleaseIFsiItems …

  { // Write... // Call to release any locks ReleaseIFsiItems(fileSystemImage.Root); // Complete tidy up... Marshal.FinalReleaseComObject(fileSystem); Marshal.FinalReleaseComObject(fileSystemImageResult); } private static void ReleaseIFsiItems(IFsiDirectoryItem rootItem) { if (rootItem == null) { return; } var enm = rootItem.GetEnumerator(); while (enm.MoveNext()) { var currentItem = enm.Current as IFsiItem; var fsiFileItem = currentItem as IFsiFileItem; if (fsiFileItem != null) { try { var stream = fsiFileItem.Data; var iUnknownForObject = Marshal.GetIUnknownForObject(stream); // Get a reference - things go badly wrong if we release a 0 ref count stream! var i = Marshal.AddRef(iUnknownForObject); // Release all references while (i > 0) { i = Marshal.Release(iUnknownForObject); } Marshal.FinalReleaseComObject(stream); } catch (COMException) { // Thrown when accessing fsiFileItem.Data } } else { ReleaseIFsiItems(currentItem as IFsiDirectoryItem); } } } 

我希望这适合你!

有一个Windows 7的修复程序解决IMAPIv2中的句柄泄漏问题。 https://support.microsoft.com/en-us/kb/2878035

出现此问题是由于在DVD-RW介质发生多区段写入会话时IMAPIv2中的句柄泄漏。