2015-06-04 1 views
3

Я использую IMAPI2FS Image Mastering API в Windows, и я пытаюсь выяснить, как добавить поток в файл в образ файловой системы, прежде чем я создам ISO.Добавление потока в ISO как файл

var fsi = new MsftFileSystemImage(); 
fsi.ChooseImageDefaultsForMediaType(IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK); 
fsi.FileSystemsToCreate = 
    FsiFileSystems.FsiFileSystemISO9660 | FsiFileSystems.FsiFileSystemJoliet; 

using (var stream = new MemoryStream()) 
{ 
    stream.Write(buffer, 0, bufferSize); 

    // Here is where I need to either instantiate an FsiStream and copy 
    // stream to it, but I can't figure out how to do this. 

    fsi.Root.AddFile(relativePathFromImageRoot, iStreamObject); 
} 

ответ

3

Вы пытаетесь использовать библиотеку типов IMAPI2FS и сталкиваетесь с общей проблемой с этой библиотекой. Он был написан довольно плохо и довольно сложно использовать непосредственно из .NET-программы. Большинство программ, ориентированных на api, были написаны на C++ и используют файл заголовка imap2fs.h SDK.

Конкретная проблема, с которой вы сталкиваетесь, заключается в том, что импортер библиотеки типов преобразовал второй аргумент AddFile() в FsiStream, тип класса. Это тип, который вы не можете создать, он имеет атрибут библиотеки [noncreatable]. Конвертер библиотеки типов был введен в заблуждение, метод фактически принимает аргумент IStream. То, что вы должны сделать, это создать свою собственную реализацию IStream и передать экземпляр из него в качестве второго аргумента.

Это можно оперировать с помощью ключевого слова C# версии 4 динамического, поэтому компилятор не собирается жаловаться на FsiStream. Вот пример класса реализации, который реализует IStream:

using System; 
using System.Runtime.InteropServices; 
using System.Runtime.InteropServices.ComTypes; 
using System.IO; 

[ComVisible(true)] 
class FsiStreamImpl : IStream { 
    private Stream source; 
    private FsiStreamImpl() { } 
    public static dynamic Create(Stream from) { 
     var stream = new FsiStreamImpl(); 
     stream.source = from; 
     return stream; 
    } 

    public void Read(byte[] pv, int cb, IntPtr pcbRead) { 
     int read = source.Read(pv, 0, cb); 
     Marshal.WriteInt32(pcbRead, read); 
    } 

    public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { 
     long pos = source.Seek(dlibMove, (SeekOrigin)dwOrigin); 
     Marshal.WriteInt64(plibNewPosition, pos); 
    } 

    public void Stat(out STATSTG pstatstg, int grfStatFlag) { 
     var stat = new STATSTG(); 
     stat.type = 2; 
     stat.cbSize = source.Length; 
     stat.grfMode = 2; 
     pstatstg = stat; 
    } 

    // Methods that we don't have to implement: 
    public void Write(byte[] pv, int cb, IntPtr pcbWritten) { 
     throw new NotImplementedException(); 
    } 
    public void Clone(out IStream ppstm) { 
     throw new NotImplementedException(); 
    } 
    public void Commit(int grfCommitFlags) { 
     throw new NotImplementedException(); 
    } 
    public void SetSize(long libNewSize) { 
     throw new NotImplementedException(); 
    } 
    public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { 
     throw new NotImplementedException(); 
    } 
    public void LockRegion(long libOffset, long cb, int dwLockType) { 
     throw new NotImplementedException(); 
    } 
    public void Revert() { 
     throw new NotImplementedException(); 
    } 
    public void UnlockRegion(long libOffset, long cb, int dwLockType) { 
     throw new NotImplementedException(); 
    } 
} 

Теперь вы можете написать код так:

using (var stream = new MemoryStream(buffer)) 
{ 
    stream.Write(buffer, 0, bufferSize); 
    stream.Position = 0; 
    fsi.Root.AddFile(relativePathFromImageRoot, FsiStreamImpl.Create(stream))); 
} 

Или код, как это то, что я испытал:

using (var file = new FileStream(@"c:\temp\test.txt", FileMode.Open, FileAccess.Read)) { 
    fsi.Root.AddFile("test.txt", FsiStreamImpl.Create(file)); 
} 

Вы могут столкнуться с некоторыми дополнительными проблемами, я проверил только те фрагменты, которые вы опубликовали. Я должен указать на это Codeproject.com project, написанный программистом, который также сражался с IMAPI2. Он принял гораздо более широкий подход, довольно опасный, и переписал всю библиотеку типов с помощью объявлений C# с ручным управлением. Он потратил много времени на это, и вопросы поддержки сосредоточены только на том, как использовать IMAPI2, чтобы вы, вероятно, были в этом уверены.

Смежные вопросы