Bumping the CD/DVD drive letter in Windows PE

While slogging through automating my development workstation build I found the need to have a script that bumps the CD/DVD drive letter allocations up one so I could put a partition in its place. It seems like a useful script for those situations where you might need it so I thought I would post it:

'===========================================================================
' Bumps the CD/DVD drive letter to the next available drive letter.
'===========================================================================
' Syntax: BumpCDDriveLetter.vbs
'===========================================================================
' Errorlevels:
'   0: Success
'   1: Invalid command line.
'   2: Unable to find any volumes.
'   3: Unable to remove existing volume mount point.
'   4: Unable to create new volume mount point.
'===========================================================================
' Revision History:
'   1.0 - 01-Jul-07 - Initial creation.
'                   - Colin Bowern (colin.bowern@officialcommunity.com)
'===========================================================================

Option Explicit

Const EVENT_SUCCESS = 0
Const EVENT_ERROR = 1
Const EVENT_WARNING = 2
Const EVENT_INFORMATION = 4

Const MountVolPath = """%SYSTEMROOT%\System32\MountVol.exe"""

If WScript.Arguments.Count <> 0 Then
    WScript.Echo "Syntax: " & WScript.ScriptName
    WScript.Quit 1
End If

Dim shell, fileSystem, wmiService, diskVolumes, diskVolume, mountPoints, _
    mountPointCount, returnCode, commandLine
Set shell = CreateObject("WScript.Shell")
Set fileSystem = CreateObject("Scripting.FileSystemObject")
Set wmiService = GetObject("winmgmts://.\root\CIMV2")
returnCode = 0
mountPointCount = 0

Set diskVolumes = wmiService.ExecQuery("SELECT * FROM Win32_Volume WHERE DriveType = '5'")
For Each diskVolume in diskVolumes
    Dim mountVolReturnCode, newDriveLetter
    newDriveLetter = GetNextAvailableDriveLetter(diskVolume.DriveLetter)
    commandLine = MountVolPath & " " & diskVolume.DriveLetter & " /d"
    mountVolReturnCode = shell.Run(commandLine, 0, True)
    If mountVolReturnCode = 0 Then
        commandLine = MountVolPath & " " & newDriveLetter & ": " & diskVolume.DeviceId
        mountVolReturnCode = shell.Run(commandLine, 0, True)
        If mountVolReturnCode = 0 Then
            mountPoints = mountPoints & diskVolume.DriveLetter & _
                " (" & diskVolume.DeviceId & ") changed to " & _
                newDriveLetter & ":" & vbCrLf
            mountPointCount = mountPointCount + 1
        Else
            LogEvent EVENT_ERROR, "Error creating new volume mount point: " & _
                mountVolReturnCode
            SetReturnCode 4
        End If
    Else
        LogEvent EVENT_ERROR, "Error removing existing volume mount point: " & _
            mountVolReturnCode
        SetReturnCode 3
    End If
Next

If mountPointCount > 0 Then
    LogEvent EVENT_SUCCESS, "Processed the following " & mountPointCount & _
        " volume(s):" & vbCrLf & mountPoints
Else
    LogEvent EVENT_INFORMATION, "No volume(s) were modified."
    SetReturnCode 2
End If


WScript.Quit returnCode

'---------------------------------------------------------------------------
' Log an event to the Event Log and Console
'---------------------------------------------------------------------------
Sub LogEvent(eventType, message)
    ' Event logs not supported by Windows PE, Windows PE starts on X: by default
    If shell.ExpandEnvironmentStrings("%SystemDrive%") <> "X:" Then
        shell.LogEvent eventType, "[" & WScript.ScriptName & "] " & message
    End If
    WScript.Echo "[" & FormatDateTime(Now, vbGeneralDate) & "] " & message
End Sub

'---------------------------------------------------------------------------
' Set the return code to the highest possible value.
'---------------------------------------------------------------------------
Sub SetReturnCode(newReturnCode)
    If returnCode < newReturnCode Then
        returnCode = newReturnCode
    End If
End Sub

'---------------------------------------------------------------------------
' Return the next available drive letter.
'---------------------------------------------------------------------------
Function GetNextAvailableDriveLetter(startingLetter)
    GetNextAvailableDriveLetter = Chr(Asc(UCase(startingLetter)) + 1)
    Do Until Not fileSystem.DriveExists(GetNextAvailableDriveLetter)
        If GetNextAvailableDriveLetter = "Z" Then
            GetNextAvailableDriveLetter = "A"
        Else
            GetNextAvailableDriveLetter = Chr(Asc(GetNextAvailableDriveLetter) + 1)
        End If
    Loop
End Function

Comments Subscribe to Post Comments Feed

Jason said:

Thanks for posting this!

I had nearly the same requirement and this does the trick.

Have Your Say