Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DVD ISO from C# - .NET DiscUtils alternatives

Tags:

c#

.net

dvd

iso9660

What is the best way to make .ISO files based on a file folder structure from C#? Is there an open source library other than DiscUtils? Running into issues with DiscUtils and I'd like try another path. What are my options? I'd prefer open source but might also be willing to pay for a solution.

like image 969
BuddyJoe Avatar asked Mar 13 '12 14:03

BuddyJoe


2 Answers

Here are some more to try

  • C# [ISO] image creator (no support for audio CDs)
  • IsoCreator
like image 146
Micah Armantrout Avatar answered Oct 05 '22 02:10

Micah Armantrout


Windows actually comes with a native API for creating ISOs and much more: the Image Mastering API. Once you grab the IMAPI2 Interop assembly from the Windows SDK or (probably easier) from this CodeProject article about IMAPI2, creating an ISO is only a few lines of code.

Unfortunately, you also need a few paragraphs to properly clean up the COM nonsense involved, but the end result is still pretty manageable:

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

iso.Root.AddTree(@"c:\path\goes\here\", false);

dynamic resultImage = iso.CreateResultImage();
dynamic imageStream = resultImage.ImageStream;
IStream newStream = null;

if (imageStream != null)
{
    STATSTG stat = null;
    imageStream.Stat(stat, 0x1);

    int res = SHCreateStreamOnFile(@"c:\path\to\your.iso", 0x1001, newStream);
    if (res == 0 && newStream != null)
    {
        IntPtr inBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(long)));
        IntPtr outBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(long)));
        try
        {
            imageStream.CopyTo(newStream, stat.cbSize, inBytes, outBytes);
        }
        finally
        {
            Marshal.FinalReleaseComObject(imageStream);
            newStream.Commit(0);
            Marshal.FinalReleaseComObject(newStream);
            Marshal.FreeHGlobal(inBytes);
            Marshal.FreeHGlobal(outBytes);
            Marshal.FinalReleaseComObject(resultImage);
            Marshal.FinalReleaseComObject(iso);
        }
    }
    else
    {
        Marshal.FinalReleaseComObject(imageStream);
        Marshal.FinalReleaseComObject(resultImage);
        Marshal.FinalReleaseComObject(iso);
        //TODO: Throw exception or do whatever to signal failure here
    }
}    
else
{
    Marshal.FinalReleaseComObject(resultImage);
    Marshal.FinalReleaseComObject(iso);
    //TODO: Throw exception or do whatever to signal failure here
}

Details for the only bit of Win32/COM API glue used can be found on pinvoke.net: SHCreateStreamOnFile. IStream and STATSTG are in System.Runtime.InteropServices.ComTypes..

like image 26
mdb Avatar answered Oct 05 '22 03:10

mdb