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:
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"
Add files to your file system:
- PS C:\Temp> $fsi.Root.AddTreeWithNamedStreams("C:\test\imt\data\2tracks")
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:
- Enumerate available recorders through MsftDiscMaster2
- PS C:\Temp> $dm = New-Object -ComObject IMAPI2.MsftDiscMaster2
- Create DiscRecorder object
- PS C:\Temp> $recorder = New-Object -ComObject IMAPI2.MsftDiscRecorder2
- 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:
- Create object
- $df2d = New-Object -ComObject IMAPI2.MsftDiscFormat2Data
- Set up recorder
- PS C:\Temp> $df2d.Recorder = $recorder
- 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:
- $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
Anonymous
December 22, 2010
#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)Anonymous
October 04, 2013
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?
Anonymous
March 04, 2015
wma? take a look on how to write the audio tracks blogs.msdn.com/.../imapi2-data-audio-track-at-once-and-audio-disc-at-once.aspxAnonymous
November 03, 2015
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