Writing optical discs using IMAPI 2 in powershell


Hello,

Today I’m going to show how to use Image Mastering API (IMAPI2) in powershell. I’m using that technique when need quickly to burn some data, in format, which is not exposed by default in Explorer. This also can be useful if you are developing some code on IMAPI2 and need some proof of concept, if that can be done using build-in windows image mastering API.

IMAPI2 is written using COM, so no additional wrappers/interops required in order to get it working in powershell. The advantage of IMAPI is the possibility to write to different medias, for example to CDRW So, let’s begin:

First of all you'll need to build in memory file system image, which will contain your files. There are few steps to achieve that:

  1. Create file system object
    • PS C:\Temp> $fsi = New-Object -ComObject IMAPI2FS.MsftFileSystemImage
    • Select appropriate settings like File System type, revision and so on
    • To view current state of any object you can just type its name in PowerShell:
      PS C:\Temp> $fsi
    • PS C:\Temp> $fsi.FileSystemsToCreate = 7
    • PS C:\Temp> $fsi.VolumeName = "MyImage"
  2. Add files to your file system:
    • PS C:\Temp> $fsi.Root.AddTreeWithNamedStreams("C:\test\imt\data\2tracks")
  3. Create result stream, that will contain your data in required format:
    • PS C:\Temp> $resultimage = $fsi.CreateResultImage()
    • PS C:\Temp> $resultStream = $resultimage.ImageStream

Actually at this step you can stop and save resulted image to the local hard disc, this will be a pure iso image.

To perform writing disc recorder needs to be initialized:

  1. Enumerate available recorders through MsftDiscMaster2
    • PS C:\Temp> $dm = New-Object -ComObject IMAPI2.MsftDiscMaster2
  2. Create DiscRecorder object
    • PS C:\Temp> $recorder = New-Object -ComObject IMAPI2.MsftDiscRecorder2
  3. Initialize recorder with unique id from discmaster2
    • PS C:\Temp> $recorder.InitializeDiscRecorder($dm.Item(0))

And Formatter, which will be used to format you filesystem image in appropriate way for recording onto your media and write data using your recorder:

  1. Create object
    • $df2d = New-Object -ComObject IMAPI2.MsftDiscFormat2Data
  2. Set up recorder
    • PS C:\Temp> $df2d.Recorder = $recorder
  3. Put client name, which will be shown for other applications, once you'll start writing
    • PS C:\Temp> $df2d.ClientName = "MyScriptBurner" Now you set up everything needed, and can start burning, just call Write from DiscFormat2Data:
  4. $df2d.Write($resultStream)

That's it! You can write data using full capabilities of IMAPI, and not even write a line of C++ code in realtime. For me it seems really useful, when you just need to write couple media, and see no way to perform to do it through standard explorer interface, and is not willing to write whole application just to perform that!

Hope this helps in Windows Image Mastering API exploring.

Mikhail

Comments (4)
  1. #All-in-one:

    param($pathToBurn = "C:testimtdata10tracks", $recorderIndex = 0, $closeMediaAfterBurn = $true)

    #create the image:

    $fsi = New-Object -ComObject "IMAPI2FS.MsftFileSystemImage"

    $fsi.FileSystemsToCreate = 7

    $fsi.VolumeName = "MyImage"

    $fsi.Root.AddTreeWithNamedStreams($pathToBurn, $false)

    $resultimage = $fsi.CreateResultImage()

    $resultStream = $resultimage.ImageStream

    #initialize the recorder:

    $dm = New-Object -ComObject "IMAPI2.MsftDiscMaster2"

    $recorder = New-Object -ComObject "IMAPI2.MsftDiscRecorder2"

    $recorder.InitializeDiscRecorder($dm.Item($recorderIndex))

    #use formatter to burn the data:

    $df2d = New-Object -ComObject IMAPI2.MsftDiscFormat2Data

    $df2d.Recorder = $recorder

    $df2d.ClientName = "MyScriptBurner"

    $df2d.ForceMediaToBeClosed = $closeMediaAfterBurn

    #burn it:

    $df2d.Write($resultStream)

  2. AddTreeWithNamedStreams failing says:

    In attempting to build an ISO image to burn to a CD-R, I have 686 MB of WMA 128 bit files in a directory tree, 1 sub-directory deep, 4 sub-directories, & 155 files which I have successfully burned using Windows File Explorer. However using PowerShell, MAPI2.MsftFileSystemImage.Root.AddTreeWithNamedStreams(directory_string, $false) results in the following message:

    Exception calling "AddTreeWithNamedStreams" with "2" argument(s): "'Adding 'my_filename.wma' would

    result in a result image having a size larger than the current configured limit.

    "

    At line:1 char:1

    + $fsi.Root.AddTreeWithNamedStreams($pathToBurn, $false)

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

       + FullyQualifiedErrorId : ComMethodTargetInvocation

    The Msft.FileSystemImage object is configured as follows:

    >$fsi

    Root                              : System.__ComObject

    SessionStartBlock                 : 0

    FreeMediaBlocks                   : 336073

    UsedBlocks                        : 528

    VolumeName                        : Celtic_Folk

    ImportedVolumeName                :

    BootImageOptions                  :

    FileCount                         : 0

    DirectoryCount                    : 1

    WorkingDirectory                  : C:UsersW1EAB~1.MARAppDataLocalTemp

    ChangePoint                       : 0

    StrictFileSystemCompliance        : False

    UseRestrictedCharacterSet         : False

    FileSystemsToCreate               : 7

    FileSystemsSupported              : 7

    UDFRevision                       : 258

    UDFRevisionsSupported             : {258, 336, 512, 513…}

    ISO9660InterchangeLevel           : 2

    ISO9660InterchangeLevelsSupported : {1, 2}

    VolumeNameUDF                     : Celtic_Folk

    VolumeNameJoliet                  : Celtic_Folk

    VolumeNameISO9660                 : CELTIC_FOLK

    StageFiles                        : False

    MultisessionInterfaces            : {}

    BootImageOptionsArray             : {}

    CreateRedundantUdfMetadataFiles   : True

    What am I doing wrong?

  3. GarThor says:

    AddTreeWithNamedStreams failing: It looks like you can get around that error if you increase the size of FreeMediaBlocks

    At which point I get stuck on the $df2d.Write() call with the following error…

    Exception calling "Write" with "1" argument(s): "Exception from HRESULT: 0xC0AA0406"

    At C:SteamOSImageWriter.ps1:38 char:12

    + $df2d.Write <<<< ($resultStream)

       + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

       + FullyQualifiedErrorId : ComMethodTargetInvocation

Comments are closed.

Skip to main content