First, some clarification of terms. By finalize, I don\'t mean closing a session; I mean writing a lead-out to a CD or DVD in such a way that information c
Set the ForceMediaToBeClosed
flag on the IMAPI2.MsftDiscFormat2Data
object and write out the disc with the close flag enabled.
Approach is described here: https://social.msdn.microsoft.com/Forums/en-US/ce1ff136-39a1-4442-bc5c-61c119b6f4f2/finalize-question?forum=windowsopticalplatform#2e968a94-7347-4d94-9332-00fe7cd0ba89
Below is a link to a nice Powershell burning script, all you'd have to do is update Out-CD
with a new param
to set $DiscFormatData.ForceMediaToBeClosed = true
when you are ready for your closing write.
Link: https://www.adamtheautomator.com/use-powershell-to-automate-burning-cds/
FYI:
# this fetches all the properties (as you probably already know)
$DiscFormatData = New-Object -com IMAPI2.MsftDiscFormat2Data ;
$DiscFormatData | Get-Member ;
The ForceMediaToBeClosed
property of IDiscFormat2Data
controls whether the IMAPI finalizes the disc after the next write:
Set to VARIANT_TRUE to mark the disc as closed to prohibit additional writes when the next write session ends.
The Image Mastering API does not provide an abstraction used specifically to finalize the disc, so we need to perform a write operation. The API will finalize a blank disc during the initial burn if we switch on ForceMediaToBeClosed
with the main image writer. For an existing multi-session disc, we need to append another session.
Here's a simple PowerShell example that we can try so we don't need to build the project. The concepts are similar in C#:
$drives = New-Object -ComObject 'IMAPI2.MsftDiscMaster2'
$recorder = New-Object -ComObject 'IMAPI2.MsftDiscRecorder2'
$recorder.InitializeDiscRecorder($drives[0]) # Choose a drive here
$disc = New-Object -ComObject 'IMAPI2.MsftDiscFormat2Data'
$disc.ClientName = 'PowerShell Recorder'
$disc.Recorder = $recorder
$disc.ForceMediaToBeClosed = $true # Finalize the next session
$image = New-Object -ComObject 'IMAPI2FS.MsftFileSystemImage'
if (!$disc.IsCurrentMediaSupported($recorder)) {
throw 'Disc is not writeable.'
} elseif ($disc.MediaHeuristicallyBlank) {
$image.ChooseImageDefaults($recorder)
} else {
$image.MultisessionInterfaces = $disc.MultisessionInterfaces
$image.ImportFileSystem() > $null
}
This sets up some boilerplate that we'll use below to burn a disc. We'll need to add error handling and capability detection for practical use, but it works fine as a demonstration. If we paste or dot-source this code into a PowerShell session, we can play with the COM objects interactively.
At this point, if we check the status of a blank or open disc, we should see a value of 2
, 4
, or 6
which correspond to the "blank" or "appendable" bitmasks (6
for both) enumerated on IMAPI_FORMAT2_DATA_MEDIA_STATE.
PS> $disc.CurrentMediaStatus # 4 for an open, multi-session disc
Then, we can add some files. If we just want to close-off a multi-session disc, we don't need to add anything to the image. The API records the session's lead-in and lead-out with an empty data track.
PS> $image.Root.AddTree('path\to\root\folder', $false)
Finally, we'll burn our changes to the disc. Because we set $disc.ForceMediaToBeClosed
to $true
, this operation finalizes the disc, and no further write operations are allowed:
PS> $disc.Write($image.CreateResultImage().ImageStream)
If we inspect the disc status now, it should indicate that the disc is not writable:
PS> $disc.CurrentMediaStatus # 16384 or 40960
For a single-session disc, we should see 16384
(0x4000
, "finalized"). My system reports 40960
for closed, multi-session discs which contains the bits 0x2000
("write-protected") and 0x8000
("unsupported media"). We may need to eject or power-cycle some hardware to see accurate values after burning.
Remarks:
In general, each session on a multi-session disc starts with a lead-in and ends with a lead-out. The lead-in of the last session permanently closes the media to further writes when we finalize a disc. This is why we need to append an additional session to an unclosed disc even if we have no more data to add.
IMAPI will automatically finalize a disc if the free space drops below 2%.
InfraRecorder—the tool mentioned in the question—does not use the IMAPI. This application provides a frontend to cdrtools which controls the device IO directly. If we just need to finalize unclosed discs, we may want to use the cdrecord CLI program included with this package to avoid maintaining an extra codebase:
PS> cdrecord -scanbus # Show <drive> IDs to choose from
PS> cdrecord -fix dev=<drive> # Close an open session
As a brief starting point, here's how we can finalize a multi-session disc:
PS> $session = cdrecord -msinfo dev=<drive>
PS> mkisofs -rJ -C $session -M <drive> 'path\to\root' | cdrecord dev=<drive> -
This achieves the same result as our PowerShell script that uses the IMAPI: we import the last session, create the image, and then burn a new session which finalizes the disc. By omitting the -multi
argument to cdrecord, the command won't write the lead-in in a way that allows for continuation of a multi-session disc.
While we typically see this toolset on Unix-like systems, builds are available for Windows.
For more advanced applications, we can use an implementation of the lower-level IDiscRecorderEx to query and send commands to the recording device.