Scripting CDs and DVDs

Introduction to the IMAPIv2

Remember the good-old-days when computers had 5 ¼” floppy disk drives? That was back in the days of the dinosaurs, when people also listened to music on records, or “LPs” as the cool kids called them. What, you don’t remember any of those? Oh, well, neither do the Scripting Guys; that was way before our time. But we’ve heard of all those things….

Of course, since then we’ve moved on to the wonderful world of CDs and DVDs. (Yes, iPods, too, but we’re not talking about those right now.) And now, with Windows Vista, Microsoft has decided to join the modern era (for the most part) and fully embrace the power of these little discs. How? By providing a scriptable application programming interface (API) that you can use to retrieve information on CD and DVD devices, read from the discs, and – yes, it’s true – write to the discs. With the new Image Mastering API (IMAPI2), you can do all these things through scripts.

In this article we’re going to introduce you to IMAPI2 by showing you how you can return a collection of all the CD/DVD devices on a computer and then read the properties from those devices. Towards the end we’ll throw in a couple methods you can use to do things like open and close the disc drives’ trays.

We know: you really want to see how to write to a CD or DVD. But it might be useful to know a couple small details first, like whether or not you even have a CD or DVD burner attached to the computer. So we’re going to start with that, and then, in Part 2, we’ll get to the fun stuff.

*
On This Page
Before We Begin…Before We Begin…
Reading Disc Recorder PropertiesReading Disc Recorder Properties
Opening and Closing the TrayOpening and Closing the Tray
More to ComeMore to Come

Before We Begin…

When this article was written, IMAPI2 was available only on Windows Vista (and the not-yet-released Windows Server 2008). Since that time the Optical Platforms team has release four downloads for earlier versions of Windows:

Image Mastering API v2.0 for Windows XP

Image Mastering API v2.0 for Windows Sever 2003

Image Mastering API v2.0 for Windows XP x64 Edition

Image Mastering API v2.0 for Windows Server 2003 x64 Edition

If you have Windows Vista you already have access to all the functionality we’re going to talk about. If you’re running Windows XP or Windows Server 2003, simply download the appropriate version then read on.

Top of pageTop of page

Reading Disc Recorder Properties

Let’s find out how to discover what type of disc drives you have connected to your computer. We’ll start by taking a look at the script:

Const IMAPI_PROFILE_TYPE_CDROM = &H8
Const IMAPI_PROFILE_TYPE_DVDROM = &H10
Const IMAPI_PROFILE_TYPE_CD_RECORDABLE = &H9
Const IMAPI_PROFILE_TYPE_DVD_PLUS_RW = &H1A

Set colDiscMaster = CreateObject("IMAPI2.MsftDiscMaster2")

For Each Id In colDiscMaster

    Set objRecorder = CreateObject("IMAPI2.MsftDiscRecorder2")
    objRecorder.InitializeDiscRecorder Id

    WScript.Echo "Vendor: " & objRecorder.VendorId
    Wscript.Echo "Product ID: " & objRecorder.ProductId
    Wscript.Echo "Product Revision: " & objRecorder.ProductRevision
    For Each strMountPoint In objRecorder.VolumePathNames
        Wscript.Echo "First Mount Point: " & strMountPoint
        Exit For
    Next
    For Each Profile In objRecorder.SupportedProfiles
        Select Case Profile
            Case IMAPI_PROFILE_TYPE_CDROM
                Wscript.Echo "IMAPI_PROFILE_TYPE_CDROM"
            Case IMAPI_PROFILE_TYPE_DVDROM
                Wscript.Echo "IMAPI_PROFILE_TYPE_DVDROM"
            Case IMAPI_PROFILE_TYPE_CD_RECORDABLE
                Wscript.Echo "CD-R"
            Case IMAPI_PROFILE_TYPE_DVD_PLUS_RW
                Wscript.Echo "DVD+RW"
        End Select
    Next
    Wscript.Echo

Next

Connecting to a Device

We start out by declaring some constants. Ignore those for now; we’ll get back to them later. Aside from declaring constants, the first thing we have to do any time we’re going to work with disc reading and writing devices is create an instance of the MsftDiscMaster2 class. We do that like this:

Set colDiscMaster = CreateObject("IMAPI2.MsftDiscMaster2")

The MsftDiscMaster2 object reference contains a collection of unique identifiers, each identifier representing a CD or DVD device connected to the computer. In other words, this isn’t actually a collection of objects that represent each device; it’s a collection of identifiers, each one, well, identifying a particular device. Kind of like a bar code on a box of cereal – just because you know the bar code doesn’t mean you actually have the cereal. If we want to work with a device, we need to use its identifier to first connect to the device; only then can we begin to work with that device. In this case we want to find all the devices, so we need to read through the collection of identifiers and retrieve each ID. We do that by using this For Each loop:

For Each Id In colDiscMaster

Each time through the loop we retrieve a device ID from the collection, assigning it to the variable Id. Once we know the device’s ID, we then connect to the device itself:

Set objRecorder = CreateObject("IMAPI2.MsftDiscRecorder2")

We now have an object reference, objRecorder, to a CD or DVD device. So we should be ready to get some properties from this device, right? Well, no, not yet. You might have noticed that, in creating the objRecorder object, we didn’t actually use our device ID; instead, we simply created a generic MsftDiscRecorder2 object. That means that right now there’s no device associated with this object reference. In other words, we have a device object, but it’s pretty useless at the moment. Before we can do anything with the device we need to specify which device we’re working with.

This is where our identifier comes in. In order to connect to a specific device we have to call the InitializeDiscRecorder method of the MsftDiscRecorder2 object, passing it the ID of the device we want to connect to, like this:

objRecorder.InitializeDiscRecorder Id

We’ve now initialized our recorder, meaning we’re ready to work with the first device in our collection.

Reading Properties

IMAPIv2 provides quite a bit of information about CD and DVD devices. We’ll start off by retrieving the name of the hardware vendor (VendorId), the product ID (ProductId), and the revision number (ProductRevision):

WScript.Echo "Vendor: " & objRecorder.VendorId
    Wscript.Echo "Product ID: " & objRecorder.ProductId
    Wscript.Echo "Product Revision: " & objRecorder.ProductRevision

Keep in mind that different hardware vendors make different information available, so some of the properties might not return any information. With any luck, we’ve chosen properties here that are pretty standard and will most likely show you some information.

The next bit of information we want is the mount points. In many cases this will simply be the drive letter of the device. A device can have multiple mount points, so we need to set up a For Each loop and read through the VolumePathNames property to retrieve each individual mount point:

For Each strMountPoint In objRecorder.VolumePathNames
        Wscript.Echo "Mount Point: " & strMountPoint
Next

Remember those constants we defined at the beginning of our script?:

Const IMAPI_PROFILE_TYPE_CDROM = &H8
Const IMAPI_PROFILE_TYPE_DVDROM = &H10
Const IMAPI_PROFILE_TYPE_CD_RECORDABLE = &H9
Const IMAPI_PROFILE_TYPE_DVD_PLUS_RW = &H1A

It’s finally time to use them. The SupportedProfiles property returns a list of, well, supported profiles. These profiles tell you whether the device is a CD-ROM, DVD-ROM, CD-R, DVD-R, and so on. Because a device can support more than one profile (for example, it might support both CDs and DVDs), we again need a For Each loop to loop through the values in this property:

For Each strProfile In objRecorder.SupportedProfiles

At this point we want to echo back the supported profiles. The problem is that SupportedProfiles contains hexadecimal values rather than nicely-readable strings such as “CD-ROM.” That’s where the constants come in. In this case we’re going to see whether the device supports CD-ROM and DVD-ROM and whether it can write to either of those. If the device can read CDs then the value returned by SupportedProfiles is hexadecimal 8; the value for DVDs is hexadecimal 10; and so on. So we’ve set up a Select Case statement and, using the constants we defined earlier, we display a string based on the hexadecimal value:

Select Case strProfile
    Case IMAPI_PROFILE_TYPE_CDROM
      Wscript.Echo "CD-ROM"
  Case IMAPI_PROFILE_TYPE_DVDROM
       Wscript.Echo "DVD-ROM"
  Case IMAPI_PROFILE_TYPE_CD_RECORDABLE
        Wscript.Echo "CD-R"
  Case IMAPI_PROFILE_TYPE_DVD_PLUS_RW
        Wscript.Echo "DVD+RW"
 End Select

There are many profiles available, but in the interest of keeping our script to a reasonable length we’ve chosen to include only these four. If you’d like to see the full list, check out MSDN.

When you run this script, you’ll receive output similar to this:

Vendor: SAMSUNG
Product ID: CD-ROM SC-148A
Product Revision: B403
Mount Point: D:\
CD-ROM

Vendor: PLEXTOR
Product ID: DVDR   PX-740A
Product Revision: 1.01
Mount Point: E:\
DVD+RW
DVD-ROM
CD-R
CD-ROM

As you can see, on the Scripting Guys’ test computer there are two devices: one on drive D: that’s CD-ROM only, another on drive E: that can read and write CDs and DVDs.

Top of pageTop of page

Opening and Closing the Tray

Now that we know how to read some properties, let’s take a look at a couple of simple methods that we can use to manipulate these devices, in particular, methods that open and close the device tray. Here’s a script that opens the tray, waits five seconds (5000 milliseconds), then closes the tray:

Set colDiscMaster = CreateObject("IMAPI2.MsftDiscMaster2")

For Each Id In colDiscMaster

    Set objRecorder = CreateObject("IMAPI2.MsftDiscRecorder2")
    objRecorder.InitializeDiscRecorder Id

    objRecorder.EjectMedia()

    Wscript.Sleep 5000

    objRecorder.CloseTray()

Next

Once again, we create a collection of all the disc device IDs on the computer by calling CreateObject and the MsftDiscMaster2 class. We then loop through the unique identifiers for each device, create a recorder object (objRecorder), then call InitializeDiscRecorder to connect to the specific device. After that it’s simple:

objRecorder.EjectMedia()

Wscript.Sleep 5000

objRecorder.CloseTray()

We call the EjectMedia method to open the tray. We then leave the tray open for five seconds, then call CloseTray to close it again.

Top of pageTop of page

More to Come

Yes, we know: this was a very short introduction to IMAPI2. But as you saw, it’s not an entirely straightforward process: you have to create an object to get the IDs, then create another object to get a device, then initialize a specific device…. that’s a lot to digest. So we’re going to take a break for now, and in Part 2 we’ll get into the really interesting stuff: burning CDs and DVDs.


Top of pageTop of page