Skip to content

Instantly share code, notes, and snippets.

@Tocchann
Created March 11, 2024 07:59
Show Gist options
  • Save Tocchann/3eb0703c398b28e1027664a00d698abf to your computer and use it in GitHub Desktop.
Save Tocchann/3eb0703c398b28e1027664a00d698abf to your computer and use it in GitHub Desktop.
IMAPI2を使ってISOイメージを保存
using System;
public class IsoImage
{
// 固定値(自動判定)
private const int mediaBlockSize = 2048;
private const long maxSizeDVD = 4488L * 512 * mediaBlockSize;
private const long maxSizeCD = 650L * 512 * mediaBlockSize;
public string SourceImageFolder { get; set; }
public string VolumeLabel { get; set; }
public void GenerateIsoImage()
{
var totalSize = CheckSourceImageSize( SourceImageFolder );
// 最終的なメディアタイプとファイルシステムを確定する
IMAPI2FS.FsiFileSystems fileSystem = IMAPI2FS.FsiFileSystems.FsiFileSystemUDF;
// CDの場合は、UDFではなく、Joliet か ISO9660 で作る
if( totalSize <= maxSizeCD )
{
fileSystem = IMAPI2FS.FsiFileSystems.FsiFileSystemJoliet | IMAPI2FS.FsiFileSystems.FsiFileSystemISO9660;
}
IMAPI2FS.MsftFileSystemImage fs = null;
try
{
fs = new IMAPI2FS.MsftFileSystemImage();
fs.ChooseImageDefaultsForMediaType( IMAPI2FS.IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK );
fs.FileSystemsToCreate = fileSystem;
fs.VolumeName = VolumeLabel;
// あらかじめメディアイメージで作り上げたツリーイメージを登録する
IMAPI2FS.IFsiDirectoryItem dirItem = null;
try
{
dirItem = fs.Root;
dirItem.AddTree( SourceImageFolder, false );
}
finally
{
Marshal.ReleaseComObject( dirItem );
}
IMAPI2FS.IFileSystemImageResult res = null;
IStream imgStm = null;
try
{
// COMのIStream 形式のデータなので、IStream.CopyTo メソッドを利用して保存する
res = fs.CreateResultImage();
imgStm = res.ImageStream as IStream;
System.Runtime.InteropServices.ComTypes.STATSTG stat;
imgStm.Stat( out stat, 0x01 );
IStream isoFile = null;
try
{
if( SHCreateStreamOnFile( IsoFilePath.ItemSpec, 0x00001001, out isoFile ) == 0 && isoFile != null )
{
imgStm.CopyTo( isoFile, stat.cbSize, IntPtr.Zero, IntPtr.Zero );
isoFile.Commit( 0 );
}
}
finally
{
Marshal.ReleaseComObject( isoFile );
}
}
finally
{
Marshal.ReleaseComObject( imgStm );
Marshal.ReleaseComObject( res );
}
}
finally
{
Marshal.ReleaseComObject( fs );
}
return true;
}
static private long CheckSourceImageSize( string checkDir )
{
long fileSize = 0;
var files = Directory.GetFiles( checkDir );
foreach( var filePath in files )
{
var fileInfo = new FileInfo( filePath );
long length = fileInfo.Length;
// ファイルごとに丸める
length = (length + (mediaBlockSize - 1)) / mediaBlockSize;
length *= mediaBlockSize;
fileSize += length;
}
var subDirs = Directory.GetDirectories( checkDir );
foreach( var subDir in subDirs )
{
fileSize += CheckSourceImageSize( subDir );
}
return fileSize;
}
[DllImport( "shlwapi.dll", CharSet = CharSet.Unicode )]
static internal extern uint SHCreateStreamOnFile( string pszFile, uint grfMode, out IStream ppstm );
}
@Tocchann
Copy link
Author

UDFのバージョンを指定する場合は、以下のようにすればいいらしい(2.6にする場合)。
fs.UDFRevision=260;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment