IMAPI2 MsftFileSystemImage in .NET not releasing files when creating ISO

后端 未结 2 1089
灰色年华
灰色年华 2021-01-19 03:33

I succesfully create the ISO image, but I get \'file in use\' IO errors trying to delete files in the rootFolderPath after returning from calling this Create method. Am I mi

相关标签:
2条回答
  • 2021-01-19 04:01

    There is a hotfix for Windows 7 solving the problem of a handle leak in IMAPIv2. https://support.microsoft.com/en-us/kb/2878035

    This problem occurs because of a handle leak in IMAPIv2 when a multisession writing session occurs for DVD-RW media.

    0 讨论(0)
  • 2021-01-19 04:06

    There is certainly a problem with locks on large files. Digging around on the net produces the following bits of the puzzle:

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

      The first answer from MS acknowledges a problem with large files. (NB setting “Staging = false” does not work for me.)

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

      Uses a stream to add files to be burned.

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

      Discusses an AddRef/Release imbalance.

    So, with all of this digested, I’ve got a solution: after Write, iterate the file system image root and release any stream data.

    There are a couple of issues for a multisession disc – as the existing files are imported (by ImportFileSystem) they all are checked for a lock and this may take some time, and a COMException is thrown for each that was not written in the current session. With a bit of effort I’m sure the difference between the file system before and after AddTree can be cached, and only those files checked.

    Anyhow... After the call to Write, we call 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);
            }
         }
      }
    

    I hope this works for you!

    0 讨论(0)
提交回复
热议问题