Created
March 11, 2024 07:59
-
-
Save Tocchann/3eb0703c398b28e1027664a00d698abf to your computer and use it in GitHub Desktop.
IMAPI2を使ってISOイメージを保存
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
UDFのバージョンを指定する場合は、以下のようにすればいいらしい(2.6にする場合)。
fs.UDFRevision=260;