如何在使用 IMAPI 创建的 ISO 文件中显式创建目录结构?

Posted

技术标签:

【中文标题】如何在使用 IMAPI 创建的 ISO 文件中显式创建目录结构?【英文标题】:How to explicitly create a directory structure in ISO file created with IMAPI? 【发布时间】:2019-03-07 02:10:42 【问题描述】:

我复制了一个使用 IMAPI 写入 ISO 文件的程序。它似乎截断了目录名称。例如,如果我调用这个函数:

image.Root.AddTree("C:\\DIR\\SUBDIR", true);

我在 ISO 中得到的是:

SUBDIR\file 1
SUBDIR\file 2
...

“DIR”部分被删除。

我想要的是:

DIR\SUBDIR\file 1
DIR\SUBDIR\file 2
...

我看过Create a folder in disk and Burn Into it using IMAPI 2,其中一个回复建议使用

rootItem.AddDirectory(directoryName);
rootItem.get_Item(directoryName, newDirItem);   

get_Item 导致编译错误“无法显式调用运算符或访问器”

关于如何在 ISO 文件中显式创建目录(并写入目录)有什么建议吗?

这里是代码。将 IMAPI2 和 IMAPI2FS 添加到引用中。

using System;
using System.IO;
using System.Runtime.InteropServices;
using IMAPI2FS;     // COM reference: Microsoft IMAPI2 File System Image Creator
using IStream = System.Runtime.InteropServices.ComTypes.IStream;
using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;

namespace CreateISO


    class IsoImage
    
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, PreserveSig = true)]
        static extern void SHCreateStreamOnFile(string pszFile, uint grfMode, out IStream ppstm);

        public void CreateISO(string path)
        
            var image = (IFileSystemImage)new MsftFileSystemImage();    // same as Activator.CreateInstance(Type.GetTypeFromProgID("IMAPI2FS.MsftFileSystemImage"))
            image.ChooseImageDefaultsForMediaType(IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK);
            image.FileSystemsToCreate = FsiFileSystems.FsiFileSystemJoliet | FsiFileSystems.FsiFileSystemISO9660;
            image.VolumeName = Path.GetDirectoryName(path);
            image.Root.AddTree(path, true);

            var inStream = (IStream)image.CreateResultImage().ImageStream;
            STATSTG stat;
            inStream.Stat(out stat, 0x01);
            IStream outStream;
            SHCreateStreamOnFile("C:\\temp\\demo.iso", 0x00001001, out outStream);

            unsafe
            
                long inBytes;
                long outBytes;
                long* pin = &inBytes;
                long* pout = &outBytes;
                inStream.CopyTo(outStream, stat.cbSize, (IntPtr)pin, (IntPtr)pout);
                outStream.Commit(0);
            
        
    

【问题讨论】:

【参考方案1】:

我想我明白了。解决方法是创建一个目录,将目录附加到ISO文件中,并将子目录添加到新对象中:

        IFsiDirectoryItem newItem = image.CreateDirectoryItem("DIR");
        image.Root.Add(newItem);
        newItem.AddTree("C:\\DIR\\SUBDIR", true);

你瞧,ISO 看起来像:

DIR\SUBDIR\file 1
DIR\SUBDIR\file 2
...

创建多级目录:

        IFsiDirectoryItem newDir = image.CreateDirectoryItem("DIR");
        IFsiDirectoryItem newDir2 = image.CreateDirectoryItem("SUBDIR1");
        image.Root.Add(newDir);   // must be added first
        newDir.Add(newDir2);
        newDir2.AddTree("C:\\DIR\\SUBDIR1\\SUBDIR2", true);

我必须说这不是我必须处理的最直观的 API。

【讨论】:

以上是关于如何在使用 IMAPI 创建的 ISO 文件中显式创建目录结构?的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在 GDAL ruby​​ 绑定中显式关闭数据集?

使用 PowerShell 创建 ISO 映像:如何将 IStream 保存到文件?

将流作为文件添加到 ISO

在 MIME 多部分消息中显式指定边界?

在 JSF 2 的 requestScoped bean 中显式创建会话