首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建ISO时IMAPI2 MsftFileSystemImage in .NET不释放文件

创建ISO时IMAPI2 MsftFileSystemImage in .NET不释放文件
EN

Stack Overflow用户
提问于 2011-10-25 23:39:49
回答 2查看 3.4K关注 0票数 5

我成功地创建了ISO映像,但是在调用这个create方法返回后,我得到了“在使用中的文件”IO错误,试图删除rootFolderPath中的文件。我错过了一个Marshal.ReleaseComObject电话吗?

代码语言:javascript
复制
/// <summary>
/// Create iso image from rootFolderPath and write to isoImageFilePath. Does not include the actual rootFolder itself
/// </summary>
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); 
    }
}
EN

回答 2

Stack Overflow用户

发布于 2011-12-10 13:59:31

大文件上的锁肯定有问题。在网络上进行挖掘会产生以下谜题:

  • http://social.msdn.microsoft.com/Forums/en-US/windowsopticalplatform/thread/5ae4a173-ccb2-4c10-8fd5-c6e59a9c0ac9

MS的第一个回答承认了一个大文件的问题。(NB设置“暂存=假”不适用于me.)

  • http://www.codeproject.com/KB/miscctrl/ISOImage.aspx?msg=2532334 )

使用流将文件添加为burned.

  • http://social.msdn.microsoft.com/Forums/en-AU/windowsopticalplatform/thread/124017ea-79c5-45e2-b62e-589b3b4505af

讨论AddRef/Release不平衡。

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

多会话磁盘有几个问题--因为现有文件是导入的(由ImportFileSystem导入)--所有这些文件都会被检查锁,这可能需要一些时间,并且对当前会话中没有写入的每个文件都抛出一个COMException。经过一点努力,我确信可以缓存AddTree之前和之后的文件系统之间的差异,并且只检查这些文件。

不管怎样..。在打电话写信之后,我们叫ReleaseIFsiItems.

代码语言:javascript
复制
       {
          // 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);
        }
     }
  }

我希望这对你有用!

票数 7
EN

Stack Overflow用户

发布于 2017-01-12 14:22:08

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

发生此问题是因为DVD-RW媒体发生多会话写入会话时,IMAPIv2中存在句柄泄漏。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7897119

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档