Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Windows introduced the new IMAPIv2.0 with the release of the Vista Operating System which was a big improvement over the original IMAPI. The original IMAPI is great for CDROMs, but it has some huge limitations like not being able to write to DVD media. I am sure this limitation is due to almost nobody having a DVD writer when Windows XP was released back in 2001. IMAPIv2 allows you to write to CD, DVD, and even Blu-ray media, as well as read and write ISO files. IMAPIv2.0 had a problem since it was only available with Windows Vista. But in June of 2007, Microsoft released update packages for Windows XP and Windows 2003. You can download the updates here.

To use the features added in the Windows Feature Pack for Storage 1.0, you need to download the update here. Windows Vista Service Pack 2 already includes the update.

I wrote this article as a sequel to my C++ article, Burning CD/DVD Media with the Image Mastering API Version 2.0. Most of the IMAPI2 samples seem to be in scripting languages. The only C# sample I found was the IBurn console project that came with the Windows Vista SDK, and more recently, the article: How to Create Optical File Images using IMAPIv2.0 by dmihailescu, which shows you how to create an ISO file.

This article was more difficult than I had thought it would be. Normally, .NET applications are supposed to be easier, but there were a number of issues that I needed to figure out to get this to work. If you're not interested in hearing me rant and rave, you can skip over the next section.

The Problems

IMAPI2 was implemented using two separate COM DLLs: imapi2.dll and imapi2fs.dll. imapi2.dll handles most of the device and recording APIs, and imapi2fs.dll handles all of the file system and IStream APIs. This may not seem like much of a problem, especially if you are using C++. This does become a huge problem with .NET, because you need to take an IStream created from IMAPI2FS and use it in IMAPI2 to write to the media. You end up getting an error message, something like this:

Unable to cast object of type 'IMAPI2FS.FsiStreamClass' to type 'IMAPI2.IStream'

Microsoft realized this problem, and created a project called IBurn that they released in the Windows Vista SDK. They created an Interop namespace that combined many classes, enums, and interfaces of IMAPI2 and IMAPI2FS into one namespace in a file Interop.cs. This fixed the problem of not being able to cast an IStream from IMAPI2FS to IMAPI2.

Unfortunately, their implementation did not completely fix my problems. I was having other COM problems, like having the application throw exceptions whenever I would try to use any method that returned an Array. I later discovered that this problem could have been fixed by changing the Array to object[]. I was also having null reference exceptions when trying to burn multiple CDs. Microsoft admits that Interop.cs is not a complete solution and is only used to demonstrate how to use IMAPI2 using C#.

So, off I went on my journey to create a complete solution.

I created two .NET Interop assemblies from the COM DLLs by using the Microsoft Type Library to Assembly Converter, tlbimp.exe. I created the two assemblies by using the following commands:

tlbimp imapi2.dll /out:imapi2int.dll
tlbimp imapi2fs.dll /out:imapi2fsint.dll

Once I had the .NET assemblies, I used Reflector to disassemble the interops and create C# source code. I combined the two files and made many modifications to the interfaces and helper classes, and added support for all interfaces of IMAPI2. That sounds a lot easier than it really was.

One of the biggest issues I had that seemed to take forever to figure out was the reversing of the get, set properties. The auto-generated code from Reflector always placed the get before the set. Many properties in IMAPI2 require that the properties be defined with set before get. If they are not in the proper order, then it causes the application to crash and instantly exit. It doesn't throw an exception to give you any kind of clue as to what the problem might be. It just kills the app. So, after I finally figured out what was wrong, I opened up the COM DLLs with the OLE/COM Object Viewer and went through the actual TypeLib for every property and made sure they were in the correct order.

I also chose not to implement the AStream interface as they did in Interop.cs. I use the System.Runtime.InteropServices.ComTypes.IStream Interface directly.

Lastly, in order to receive notifications for all events, I had to go through the SDK and find all of the Dispatch IDs for all of the events. Without these values, the event handlers are unable to receive notifications.

New IMAPI2 Interop - Imapi2interop.cs

My replacement for Interop.cs is Imapi2Interop.cs, included in the source code. It defines the following classes and interfaces:

The Windows Feature Pack for Storage 1.0 also adds the following Interfaces:

It also defines the following events:

Using the Code

Make sure that XP and 2003 have the IMAPI2 updates mentioned at the top of the article.

Do not add the imapi2.dll and imapi2fs.dll COM DLLs to your project. That will cause the problems listed above.

Add the file imapi2interop.cs to your project and define the namespace in your app:

using IMAPI2.Interop;

In order to receive notification to your event handler from COM, you need to open up the file AssemblyInfo.cs and change the ComVisible attribute to true:

[assembly: ComVisible(true)]

Determining the Media Type

To determine the media type and the available space on the hard drive, you create a MsftDiscFormat2Data object and set the current recorder in the Recorder property. You can then get the media type from the IDiscFormat2Data CurrentPhysicalMediaType property.

Once you have the media type, create a MsftFileSystemImage object and call the ChooseImageDefaultsForMediaType method with the media type.

To determine if any sessions have already been recorded on the media, check the IDiscFormatData2 MediaHeuristicallyBlank property.

If it is false, then other sessions have been recorded and you need to set the MsftFileSystemImage's MultisessionInterfaces property with the IDiscFormat2Data MultisessionInterfaces property, then call the IDiscFormat2Data ImportFileSystem() method.

Then, get the free media blocks by multiplying the MsftFileSystemImage's FreeMediaBlocks with the sector size (2048). If there were previous sessions recorded on the media, that space will be subtracted from the total size of the media.

private void buttonDetectMedia_Click(object sender, EventArgs e)
{
    IDiscRecorder2 discRecorder =
        (IDiscRecorder2)devicesComboBox.Items[devicesComboBox.SelectedIndex];
 
    MsftFileSystemImage fileSystemImage = null;
    MsftDiscFormat2Data discFormatData = null;
 
    try
    {
        //
        // Create and initialize the IDiscFormat2Data
        //
        discFormatData = new MsftDiscFormat2Data();
        if (!discFormatData.IsCurrentMediaSupported(discRecorder))
        {
            labelMediaType.Text = "Media not supported!";
            totalDiscSize = 0;
            return;
        }
        else
        {
            //
            // Get the media type in the recorder
            //
            discFormatData.Recorder = discRecorder;
            IMAPI_MEDIA_PHYSICAL_TYPE mediaType =
                discFormatData.CurrentPhysicalMediaType;
            labelMediaType.Text = GetMediaTypeString(mediaType);
 
            //
            // Create a file system and select the media type
            //
            fileSystemImage = new MsftFileSystemImage();
            fileSystemImage.ChooseImageDefaultsForMediaType(mediaType);
 
            //
            // See if there are other recorded sessions on the disc
            //
            if (!discFormatData.MediaHeuristicallyBlank)
            {
                fileSystemImage.MultisessionInterfaces =
                discFormatData.MultisessionInterfaces;
                fileSystemImage.ImportFileSystem();
            }
 
            Int64 freeMediaBlocks = fileSystemImage.FreeMediaBlocks;
            totalDiscSize = 2048 * freeMediaBlocks;
        }
    }
    catch (COMException exception)
    {
        MessageBox.Show(this, exception.Message, "Detect Media Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    finally
    {
        if (discFormatData != null)
        {
            Marshal.ReleaseComObject(discFormatData);
            discFormatData = null;
        }
 
        if (fileSystemImage != null)
        {
            Marshal.ReleaseComObject(fileSystemImage);
            fileSystemImage = null;
        }
    }
 
    UpdateCapacity();
}

Adding Files and Directories to the Listbox

I created a generic interface called IMediaItem. IMediaItem contains three properties and one method:

interface IMediaItem
{
    /// <summary>
    /// Returns the full path of the file or directory
    /// </summary>
    string Path { get; }
 
    /// <summary>
    /// Returns the size of the file or directory to the next largest sector
    /// </summary>
    Int64 SizeOnDisc { get; }
 
    /// <summary>
    /// Returns the Icon of the file or directory
    /// </summary>
    System.Drawing.Image FileIconImage { get; }
 
    // Adds the file or directory to the directory item, usually the root.
    bool AddToFileSystem(IFsiDirectoryItem rootItem);
}

For file items, I created the FileItem class. This class basically creates an IStream by PInvoking the SHCreateStreamOnFile Windows API call, and adds it to IFsiDirectoryItem.

For directory items, I created the DirectoryItem class. This uses a much simpler technique of calling the IFsiDirectoryItem.AddTree method to add the directory and all subdirectories to the IStream.

These classes and interfaces are located in the IMediaItem.cs file.

Creating the Image

I use the CreateMediaFileSystem method in the MainForm class to create the IStream image to write to the media. I enumerate through the files and directories that were added to the file listbox.

private bool CreateMediaFileSystem(IDiscRecorder2 discRecorder, out IStream dataStream)
{
    MsftFileSystemImage fileSystemImage = null;
    try
    {
        fileSystemImage = new MsftFileSystemImage();
        fileSystemImage.ChooseImageDefaults(discRecorder);
        fileSystemImage.FileSystemsToCreate =
            FsiFileSystems.FsiFileSystemJoliet | FsiFileSystems.FsiFileSystemISO9660;
        fileSystemImage.VolumeName = textBoxLabel.Text;
 
        fileSystemImage.Update +=
        new DFileSystemImage_EventHandler(fileSystemImage_Update);
 
        //
        // If multisessions, then import previous sessions
        //
        if (multisessionInterfaces != null)
        {
            fileSystemImage.MultisessionInterfaces = multisessionInterfaces;
            fileSystemImage.ImportFileSystem();
        }
 
        //
        // Get the image root
        //
        IFsiDirectoryItem rootItem = fileSystemImage.Root;
 
        //
        // Add Files and Directories to File System Image
        //
        foreach (IMediaItem mediaItem in listBoxFiles.Items)
        {
            //
            // Check if we've cancelled
            //
            if (backgroundBurnWorker.CancellationPending)
            {
                break;
            }
 
            //
            // Add to File System
            //
            mediaItem.AddToFileSystem(rootItem);
        }
 
        fileSystemImage.Update -=
        new DFileSystemImage_EventHandler(fileSystemImage_Update);
 
        //
        // did we cancel?
        //
        if (backgroundBurnWorker.CancellationPending)
        {
            dataStream = null;
            return false;
        }
 
        dataStream = fileSystemImage.CreateResultImage().ImageStream;
    }
    catch (COMException exception)
    {
        MessageBox.Show(this, exception.Message, 
            "Create File System Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
        dataStream = null;
        return false;
    }
    finally
    {
        if (fileSystemImage != null)
        {
            Marshal.ReleaseComObject(fileSystemImage);
        }
    }
 
    return true;
}

Multithreading

Burning or formatting media can take some time, so we do not want to perform these actions on the main UI thread. I use the BackgroundWorker class to handle the multithreading of these lengthy tasks. The BackgroundWorker class allows you to set values within the thread and then call the ReportProgress method which fires a ProgressChanged event in the calling thread. When you are finished with your worker thread, it fires the RunWorkerCompleted event to notify the calling thread that it is finished. I won't go into much detail on the whole threading process since that is not the main topic of this article.

Writing Data to Media

I write the data in the MainForm's backgroundBurnWorker_DoWork which is the DoWork event for the BackgroundWorker backgroundBurnWorker.

private void backgroundBurnWorker_DoWork(object sender, DoWorkEventArgs e)
{
    MsftDiscRecorder2 discRecorder = null;
    MsftDiscFormat2Data discFormatData = null;
 
    try
    {
        //
        // Create and initialize the IDiscRecorder2 object
        //
        discRecorder = new MsftDiscRecorder2();
        BurnData burnData = (BurnData)e.Argument;
        discRecorder.InitializeDiscRecorder(burnData.uniqueRecorderId);
 
        //
        // Create and initialize the IDiscFormat2Data
        //
        discFormatData = new MsftDiscFormat2Data();
        discFormatData.Recorder = discRecorder;
        discFormatData.ClientName = m_clientName;
        discFormatData.ForceMediaToBeClosed = checkBoxCloseMedia.Checked;
 
        //
        // Set the verification level
        //
        IBurnVerification burnVerification = (IBurnVerification)discFormatData;
        burnVerification.BurnVerificationLevel =
            (IMAPI_BURN_VERIFICATION_LEVEL)m_verificationLevel;
 
        //
        // Check if media is blank, (for RW media)
        //
        object[] multisessionInterfaces = null;
        if (!discFormatData.MediaHeuristicallyBlank)
        {
            multisessionInterfaces = discFormatData.MultisessionInterfaces;
        }
 
        //
        // Create the file system
        //
        IStream fileSystem = null;
        if (!CreateMediaFileSystem(discRecorder, 
             multisessionInterfaces, out fileSystem))
        {
            e.Result = -1;
            return;
        }
 
        //
        // add the Update event handler
        //
        discFormatData.Update += 
            new DiscFormat2Data_EventHandler(discFormatData_Update);
 
        //
        // Write the data here
        //
        try
        {
            discFormatData.Write(fileSystem);
            e.Result = 0;
        }
        catch (COMException ex)
        {
            e.Result = ex.ErrorCode;
            MessageBox.Show(ex.Message, "IDiscFormat2Data.Write failed",
                MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
        finally
        {
            if (fileSystem != null)
            {
                Marshal.FinalReleaseComObject(fileSystem);
            }
        }
 
        //
        // remove the Update event handler
        //
        discFormatData.Update -= 
          new DiscFormat2Data_EventHandler(discFormatData_Update);
 
        if (this.checkBoxEject.Checked)
        {
            discRecorder.EjectMedia();
        }
 
    }
    catch (COMException exception)
    {
        //
        // If anything happens during the format, show the message
        //
        MessageBox.Show(exception.Message);
        e.Result = exception.ErrorCode;
    }
    finally
    {
        if (discRecorder != null)
        {
            Marshal.ReleaseComObject(discRecorder);
        }
 
        if (discFormatData != null)
        {
            Marshal.ReleaseComObject(discFormatData);
        }
    }
}

Progress Update Events

The IDiscFormat2Data supports cancelling with the CancelWrite method. When I receive the Update Event from IDiscFormatData2, I check to see if the user pressed the Cancel button. If the user has cancelled, the BackgroundWorker's CancellationPending property will be true, and I cancel the write operation and immediately return. Otherwise, I collect the data from the IDiscFormat2DataEventArgs object, then call the backgroundBurnWorker.ReportProgress so the UI thread can update the data and progress bar.

void discFormatData_Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender,
                           [In, MarshalAs(UnmanagedType.IDispatch)] objectprogress)
{
    //
    // Check if we've cancelled
    //
    if (backgroundBurnWorker.CancellationPending)
    {
        IDiscFormat2Data format2Data = (IDiscFormat2Data)sender;
        format2Data.CancelWrite();
        return;
    }
    IDiscFormat2DataEventArgs eventArgs = (IDiscFormat2DataEventArgs)progress;
    m_burnData.task = BURN_MEDIA_TASK.BURN_MEDIA_TASK_WRITING;
    // IDiscFormat2DataEventArgs Interface
    m_burnData.elapsedTime = eventArgs.ElapsedTime;
    m_burnData.remainingTime = eventArgs.RemainingTime;
    m_burnData.totalTime = eventArgs.TotalTime;
    // IWriteEngine2EventArgs Interface
    m_burnData.currentAction = eventArgs.CurrentAction;
    m_burnData.startLba = eventArgs.StartLba;
    m_burnData.sectorCount = eventArgs.SectorCount;
    m_burnData.lastReadLba = eventArgs.LastReadLba;
    m_burnData.lastWrittenLba = eventArgs.LastWrittenLba;
    m_burnData.totalSystemBuffer = eventArgs.TotalSystemBuffer;
    m_burnData.usedSystemBuffer = eventArgs.UsedSystemBuffer;
    m_burnData.freeSystemBuffer = eventArgs.FreeSystemBuffer;
    //
    // Report back to the UI
    //
    backgroundBurnWorker.ReportProgress(0, m_burnData);
}

Formatting/Erasing RW Discs

burnmedia_format.png

I format the disc in the MainForm's backgroundFormatWorker_DoWork which is the DoWork event for the BackgroundWorker backgroundFormatWorker.

private void backgroundFormatWorker_DoWork(object sender, DoWorkEventArgs e)
{
    MsftDiscRecorder2 discRecorder = null;
    MsftDiscFormat2Erase discFormatErase = null;
 
    try
    {
        //
        // Create and initialize the IDiscRecorder2
        //
        discRecorder = new MsftDiscRecorder2();
        string activeDiscRecorder = (string)e.Argument;
        discRecorder.InitializeDiscRecorder(activeDiscRecorder);
 
        //
        // Create the IDiscFormat2Erase and set properties
        //
        discFormatErase = new MsftDiscFormat2Erase();
        discFormatErase.Recorder = discRecorder;
        discFormatErase.ClientName = m_clientName;
        discFormatErase.FullErase = !checkBoxQuickFormat.Checked;
 
        //
        // Setup the Update progress event handler
        //
        discFormatErase.Update +=
        new DiscFormat2Erase_EventHandler(discFormatErase_Update);
 
        //
        // Erase the media here
        //
        try
        {
            discFormatErase.EraseMedia();
            e.Result = 0;
        }
        catch (COMException ex)
        {
            e.Result = ex.ErrorCode;
            MessageBox.Show(ex.Message, "IDiscFormat2.EraseMedia failed",
                MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
 
        //
        // Remove the Update progress event handler
        //
        discFormatErase.Update -=
        new DiscFormat2Erase_EventHandler(discFormatErase_Update);
 
        //
        // Eject the media
        //
        if (checkBoxEjectFormat.Checked)
        {
            discRecorder.EjectMedia();
        }
 
    }
    catch (COMException exception)
    {
        //
        // If anything happens during the format, show the message
        //
        MessageBox.Show(exception.Message);
    }
    finally
    {
        if (discRecorder != null)
        {
            Marshal.ReleaseComObject(discRecorder);
        }
 
        if (discFormatErase != null)
        {
            Marshal.ReleaseComObject(discFormatErase);
        }
    }
}

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralDoes this work in vista?
johnnycrash99
11:32 27 Oct '09  
This is what happens when i run in vista. When I run in xp after downloading the IMAPI2 patches it works. IMAPI2 works in vista, since I was able to write a vb6 app to do everything.

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.InvalidCastException: Unable to cast COM object of type 'IMAPI2.Interop.MsftDiscFormat2DataClass' to interface type 'IMAPI2.Interop.IBurnVerification'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{D2FFD834-958B-426D-8470-2A13879C6A91}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
at BurnMedia.MainForm.backgroundBurnWorker_DoWork(Object sender, DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)


************** Loaded Assemblies **************
mscorlib
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3074 (QFE.050727-3000)
CodeBase: file:///C:/Windows/Microsoft.NET/Framework64/v2.0.50727/mscorlib.dll
----------------------------------------
BurnMedia
Assembly Version: 1.0.0.0
Win32 Version: 1.0.0.0
CodeBase: file:///C:/Users/jfranco/Desktop/BurnMedia.exe
----------------------------------------
System.Windows.Forms
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
CustomMarshalers
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/Windows/assembly/GAC_64/CustomMarshalers/2.0.0.0__b03f5f7f11d50a3a/CustomMarshalers.dll
----------------------------------------

************** JIT Debugging **************
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.

For example:

<configuration>
<system.windows.forms jitDebugging="true" />
</configuration>

When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.
GeneralRe: Does this work in vista?
Eric Haddan
18:08 27 Oct '09  
The IBurnVerification interface requires the Windows Feature Pack for Storage[^] update
GeneralHRESULT E_FAIL
nghiaap
19:56 16 Oct '09  
Please help, I got Error message:
HRESULT E_FAIL has been returned from a call to a COM component

the title: Error: -2147467259- please install IMAPI2

I've already install updated from links:
Image Mastering API v2.0 (IMAPIv2.0) for Windows XP (KB932716)
and IMAPI_XP_SRV2003_x86.exe
using XP sp3

nghiaap

GeneralRe: HRESULT E_FAIL
Eric Haddan
5:59 17 Oct '09  
What function did this fail on? What were the parameters?
GeneralRe: HRESULT E_FAIL
nghiaap
6:55 17 Oct '09  
I tried to run the demo file (.exe)

nghiaap

GeneralRe: HRESULT E_FAIL
Eric Haddan
7:58 19 Oct '09  
Can you download the source and let me know which function fails with E_FAIL and the parameters?
GeneralRe: HRESULT E_FAIL
Member 4162170
10:58 16 Nov '09  
Hi,

on my side it seems happen through going through the "uniqueRecorderID" in MainForm_Load

uniqueRecorderID =
\\?\scsi#cdrom&ven_fare&prod_34xqjsd2zk1&rev_1.03#5&36e5972&0&000#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}

which seems to be my Deamon Tool.

So I changes the code like this..

foreach (string uniqueRecorderID in discMaster)
{
MsftDiscRecorder2 discRecorder2 = new MsftDiscRecorder2();
try
{

discRecorder2.InitializeDiscRecorder(uniqueRecorderID);
devicesComboBox.Items.Add(discRecorder2);
}
catch
{
// something is strange... hmmm
}
}

Anyway thank you for this great piece of code. I was looking for something a long time.
Great works!

Mark
GeneralRe: HRESULT E_FAIL [modified]
Kent Andersson
5:54 16 Jan '10  
I got the same error on one of my laptops running Windows XP SP3, what I suspect is Daemon Tool, I got version 4.30.1 on this computer.
I'm currently installing Visual Studio in this computer so I could do some debugging.

The reason I suspect Daemon tools is that I don't get that "CD/DVD" in the list of available drives.
The program works apart from this error message.

/Kent Andersson

To Eric: You've done a great work with this!

modified on Saturday, January 16, 2010 11:39 AM

GeneralRe: HRESULT E_FAIL
Eric Haddan
9:37 16 Jan '10  
Thanks for the information! Hopefully it could help others too.
GeneralRe: HRESULT E_FAIL
nghiaap
7:43 17 Oct '09  
hi Eric
look like the update have no affect
I tried http://www.codeproject.com/KB/winsdk/IMAPI2.aspx demo, and get empty devices on dropdown
how to check if IMAPI v2 installed

nghiaap

QuestionCreating stand alone DVD Player compatible DVDs
jlgeris
8:21 1 Oct '09  
First off, thanks Eric for sharing your knowledge.

I've been using an adaptation of your code to burn some DVDs from files i created with the program DVDAuthor. I can play the DVDs on multiple computers without too much of a problem, but the problem is when I try to play the DVD (- or +) on a OTS DVD player hooked up to my TV. I've tried multiple DVD players, and I don't believe that's the problem. I'm wondering if anybody here has any insight in creating a DVD with the appropriate file system, settings, etc. to use a standard player. I'm using the following file structure:
fileSystemImage.FileSystemsToCreate =
FsiFileSystems.FsiFileSystemJoliet | FsiFileSystems.FsiFileSystemISO9660 | FsiFileSystems.FsiFileSystemUDF;

along with setting discFormatData.ForceMediaToBeClosed = true;
I'm also not aware of any need to finalize the disc unless I made this a multisession.

Thanks, and any help would be appreciated.
GeneralAudio CDs?
mcgin1591
10:11 28 Sep '09  
Seems that i can burn audio to a disc and listen to it but when i try to play in my car it will not, it works when i use WMP to burn though. I think im burning it as a data cd instead of audio, not sure though. What would be your guess? Anyone?
GeneralRe: Audio CDs?
Eric Haddan
10:43 28 Sep '09  
If you're not sure, then I'm pretty sure you made a data cd. I wrote another article on how to create an audio CD here[^]. (Correction: It's already in C#)
GeneralRe: Audio CDs?
mcgin1591
18:23 28 Sep '09  
Thanks, thats what im looking for. Does that work for mp3 files also?
GeneralRe: Audio CDs?
Eric Haddan
18:56 28 Sep '09  
No, sorry you would need to convert the MP3 files to wave files that are 44.1 Hz, 16-bit, stereo, uncompressed PCM format. The article does not handle the conversion, but I'm sure there are some examples that you can find.
GeneralRe: Audio CDs?
mcgin1591
19:00 28 Sep '09  
Alright thanks!
GeneralReading and extracting ISO image files
otakucode
16:52 22 Sep '09  
First, thanks very much for such a great article and all of your hard work. What I am looking for is a way to read an existing disc image in ISO format and extract the contents. Are these objects capable of that?
GeneralRe: Reading and extracting ISO image files
Eric Haddan
17:21 22 Sep '09  
Thanks for answering the other question. Smile No, these interfaces are not capable of reading ISO files because they do not provide any methods to import the iso stream into the IFileSystemImage. You may want to check out the CodePlex project ImageMaster[^]. It is written in C# and they also use IMAPI for burning.
GeneralHow Do I...
rspercy60
7:43 21 Sep '09  
Hi Eric...
I downloaded the app above and converted it to VB.Net. I then stripped out all the the subs and the tab that had to do with formatting the disc. I really didnt need this part as I only use blank DVD-R disc's. What I would like to know is, How would I add a menu to the dvd? (ex.)

1. Name of avi file.avi
2. Name of next File.avi
3. and so...
(/ex.)

When the dvd is inserted in the dvd player I want the menu to show on the TV screen with the first
file highlighted for play or select a different movie by scrolling up or down with the remote,
something like DivX Player when it burns files.

I hope you can help me with this as I think it would be a nice app to add to codeproject.

Thanks for your time and patience.

rspercy
If "You wash your feet and find a pair of socks " Then
"You ARE a Redneck"
End If

GeneralRe: How Do I...
otakucode
16:48 22 Sep '09  
What you want to do is far, far, far beyond the scope of this project. This project simply allows you to write an image to a disc. What you want to do is read and convert video and audio formats (from AVI to DVD-compliant MPEG-2 streams), create a menu automatically which would involve programmatically generating and rendering MPEG-2 video and audio, then finally compile all of that into an image in the DVD-Video format. This is a tremendous amount of work and a very far-reaching project.

AVI files can contain a multitude of different types of audio and video of different formats. Only MPEG-2 format audio and video is allowed on a DVD. DVD menus have their own special format. I don't know much about it, but it is certainly not a trivial thing to manipulate. Converting video and audio is, of course, extremely complex in its own right... difficult to do, and even more difficult to do competently and produce good-quality output. In order for a set of MPEG-2 video and audio to be able to be played by a DVD player, the video and audio must all be packaged into VOB files with IFO metadata files riding alongside in a specific directory structure. Once you get all of that done, then this project would enable you to add that folder structure to an image and burn the disc. What you want to do is certainly possible, but is a task of very high difficulty and a very large quantity of work above and beyond simply being able to burn a disc.

Good luck!
otakucode
GeneralRe: How Do I...
rspercy60
6:27 23 Sep '09  
I am some-what new to VB and I would like to thank you for not advising me to go down this path. Fo now I'll leave it to the pros.

Once again Thanks for the quick reply and a very good explanation on how this has to be done.

rspercy
If "You wash your feet and find a pair of socks " Then
"You ARE a Redneck"
End If

GeneralRe: How Do I... [modified]
SunMee
23:45 22 Dec '09  
Hi,

You can use FFMPEG to convert any video format to mpeg2.
DVDAUTHOR to create dvd structure folder (VOB files with IFO metadata files).
then you can write it and play it any dvd player. Have a look at this and enjoy.

ffmpeg documentation.
http://ffmpeg.org/ffmpeg-doc.html[^]

Dvdauthor documentation
http://dvdauthor.sourceforge.net/doc/index.html[^]

for windows downloads.
http://www.paehl.com/open_source/?DVDAuthor[^]

regards,

Sundaram.

modified on Wednesday, December 23, 2009 4:57 AM

GeneralRe: How Do I...
rspercy60
5:43 23 Dec '09  
Thank You,...DVD Author is exactly what I needed.

rspercy
If "You wash your feet and find a pair of socks " Then
"You ARE a Redneck"
End If

QuestionRecent COM issues
Roddg
10:52 25 Aug '09  
hi, I had been using a version of this project with a C++ application through COM. Everything was fine a couple months ago, but today I rebuilt the .tlb file for this project and when I try importing it into my C++ application I get the following errors:
warning C4336: import cross-referenced type library 'C:\WINDOWS\system32\IMAPI2fs.dll' before importing 'Archive.tlb'
Also, everywhere IDiscRecorder2Ptr is referenced in the .tlh and tli files during the C++ application build I get an error.

This same code was working fine a couple months ago, so maybe a recent Windows Update changed something but I was curious if anyone had an idea

thanks! Smile
GeneralRe: Recent COM issues
Roddg
5:07 27 Aug '09  
I think I might have made some headway on this... when I build this project and have "Register for COM Interop" checked in the project properties I get the following warning message.

C:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets : warning : Type library exporter warning processing 'IMAPI2.Interop.IBootOptions.get_BootImage(#0), Test.Archive'. Warning: Type library exporter could not find the type library for 'System.Runtime.InteropServices.ComTypes.IStream'. IUnknown was substituted for the interface.

Previously, this did not seem to cause any issues for me so I was ignoring it. But at the end of July, Microsoft released a security update (KB971092) for Visual Studio 2008 that is COM specific. I'm wondering if this IUnknown might be causing me some grief.

Anyone know how I could resolve this warning?

http://support.microsoft.com/kb/971092
http://www.microsoft.com/technet/security/bulletin/MS09-035.mspx
http://msdn.microsoft.com/en-us/visualc/ee309358.aspx


Last Updated 2 Mar 2010 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010