{"id":42,"date":"2008-10-19T03:20:27","date_gmt":"2008-10-18T18:20:27","guid":{"rendered":"http:\/\/www.jhouseconsulting.com\/index.php\/jhouseconsulting\/2008\/10\/19\/intelligently-changing-the-drive-letter-assignment-for-multiple-cddvd-rom-drives\/"},"modified":"2012-06-21T07:50:02","modified_gmt":"2012-06-20T23:50:02","slug":"intelligently-changing-the-drive-letter-assignment-for-multiple-cddvd-rom-drives","status":"publish","type":"post","link":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2008\/10\/19\/intelligently-changing-the-drive-letter-assignment-for-multiple-cddvd-rom-drives-42","title":{"rendered":"Intelligently changing the drive letter assignment for multiple CD\/DVD ROM Drives"},"content":{"rendered":"<p>Diskpart\u00a0may fail when creating more than one partition when executing the &#8220;assign letter=D&#8221; command. This is because Windows, WinPE included, by default assigns the first CD-ROM &#8220;type&#8221; drive to the first available letter after C:.\u00a0So if you are partitioning a new server, or repartitioning a server that contains only 1 partition (C:), the CD-ROM drive will be assigned to D:. Therefore, if you were creating more than one partition and wanted to assign letter D: to the second partition, it would fail.<!--more--><\/p>\n<p>The other challenge is that sometimes you may see more than one CD-ROM &#8220;type&#8221; drive, as booting up using an ISO image is considered to be one, plus the server may actually have a physical one too, which would be assigned to letter E:.<\/p>\n<p>The script below searches all logical disks, locates the\u00a0CD-ROM &#8220;type&#8221; drives,\u00a0and changes their drive letters starting from Z: and working backwards. This ensure that they do not interfere with any further Diskpart operations.<\/p>\n<p>I have used two arrays:<\/p>\n<ol>\n<li>arrReservedDrives &#8211; used to reserve drive letters D:, E: and F:. If a CD-ROM &#8220;type&#8221; drive matches these letters, its drive letter is changed. You can certainly add letters to, or remove letters from\u00a0this array.<\/li>\n<li>arrReservedLetters &#8211; used to reserve any other drive letters, such as network drives, etc. I have reserved I: and S: because those are network drives used by my automated build process.<\/li>\n<\/ol>\n<p>You could easily extend this script to also manage the drive letters assigned to removable drives, etc.<\/p>\n<p>Enjoy!!!<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' This script will change the drive letter of any CD\/DVD ROM drive(s) attached to a drive letter that is\r\n' not in use starting from the Z: drive.\r\n' It will also change the letter of any Removable Disks. This is to manage the Virtual Floppy device\r\n' presented from the Dell Remote Access Controller (DRAC), which by default is connected starting from\r\n' the letter C, and will break the Disk partitioning process.\r\n\r\n' Release 1.3 Modified by Jeremy@jhouseconsulting.com on 14th June 2010\r\n' Written by Jeremy@jhouseconsulting.com on 30th September 2008.\r\n\r\nOption Explicit\r\n\r\nDim blnDebug, arrReservedDrives, strComputer, objWMIService, colDisks, objDisk, strNewDriveLetter, x\r\n\r\nblnDebug = False\r\n\r\n' Drive C: is always reserved. This array is setup to ensure that we reserve the first 6 drive letters for\r\n' Fixed Disk partitions\/volumes and H is typically used as a network home drive.\r\narrReservedDrives = Array (&quot;C:&quot;,&quot;D:&quot;,&quot;E:&quot;,&quot;F:&quot;,&quot;G:&quot;,&quot;H:&quot;)\r\n\r\n  strComputer = &quot;.&quot;\r\n  Set objWMIService = GetObject(&quot;winmgmts:\\\\&quot; &amp; strComputer &amp; &quot;\\root\\cimv2&quot;)\r\n  Set colDisks = objWMIService.ExecQuery(&quot;Select * from Win32_LogicalDisk&quot;)\r\n  For Each objDisk in colDisks\r\n    Select Case objDisk.DriveType\r\n      Case 0\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is an Unknown device.&quot;\r\n      Case 1\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; has No Root Directory.&quot;\r\n      Case 2\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is a Removable Disk.&quot;\r\n        If instr(1,objDisk.Description,&quot;Removable Disk&quot;,1) &gt; 0 Then\r\n          For x=0 to Ubound(arrReservedDrives)\r\n            If StrComp(arrReservedDrives(x),objDisk.DeviceID) = 0 Then\r\n              wscript.echo &quot;There is a &quot; &amp; objDisk.Description &amp; &quot; connected as drive &quot; &amp; objDisk.DeviceID\r\n              strNewDriveLetter=FindAvailableDriveLetter(&quot;Descending&quot;)\r\n              Call ChangeDriveLetter(objDisk.DeviceID,strNewDriveLetter)\r\n              wscript.echo &quot;Changed the &quot; &amp; objDisk.Description &amp; &quot; from &quot; &amp; objDisk.DeviceID &amp; &quot; to &quot; &amp; strNewDriveLetter\r\n            End If\r\n          Next\r\n        End If\r\n      Case 3\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is a Local (Fixed) Disk.&quot;\r\n      Case 4\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is a Network Drive.&quot;\r\n      Case 5\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is a CD-ROM or DVD-ROM Drive.&quot;\r\n        For x=0 to Ubound(arrReservedDrives)\r\n          If StrComp(arrReservedDrives(x),objDisk.DeviceID) = 0 Then\r\n            wscript.echo &quot;There is a &quot; &amp; objDisk.Description &amp; &quot; connected as drive &quot; &amp; objDisk.DeviceID\r\n            strNewDriveLetter=FindAvailableDriveLetter(&quot;Descending&quot;)\r\n            Call ChangeDriveLetter(objDisk.DeviceID,strNewDriveLetter)\r\n            wscript.echo &quot;Changed the &quot; &amp; objDisk.Description &amp; &quot; from &quot; &amp; objDisk.DeviceID &amp; &quot; to &quot; &amp; strNewDriveLetter\r\n          End If\r\n        Next\r\n      Case 6\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is a RAM Disk.&quot;\r\n      Case Else\r\n        If blnDebug Then wscript.echo objDisk.DeviceID &amp; &quot; is an undocumented device type.&quot;\r\n    End Select\r\n  Next\r\n\r\nSet objWMIService = Nothing\r\nSet colDisks = Nothing\r\n\r\nwscript.quit(0)\r\n\r\nSub ChangeDriveLetter(strCurrentLetter,strNewLetter)\r\n  Dim arrDefaultString, WshShell, objFSO, strDiskPartFile, objOutFile, strCommandLine\r\n  Const FOR_WRITING = 2\r\n  arrDefaultString = Array (&quot;select volume &quot;, &quot;remove noerr&quot;, &quot;assign letter &quot;, &quot;exit&quot;)\r\n  set WshShell = WScript.CreateObject(&quot;WScript.Shell&quot;)\r\n  Set objFSO = CreateObject(&quot;Scripting.FileSystemObject&quot;)\r\n  strDiskPartFile = WshShell.ExpandEnvironmentStrings(&quot;%TEMP%\\Diskpart.txt&quot;)\r\n  Set objOutFile = objfso.CreateTextFile(strDiskPartFile, True)\r\n  objOutFile.WriteLine arrDefaultString(0) &amp; strCurrentLetter\r\n  objOutFile.WriteLine arrDefaultString(1)\r\n  objOutFile.WriteLine arrDefaultString(2) &amp; strNewLetter\r\n  objOutFile.WriteLine arrDefaultString(3)\r\n  objOutFile.close\r\n  strCommandLine = &quot;diskpart.exe \/S &quot; &amp; chr(34) &amp; strDiskPartFile &amp; chr(34)\r\n  WshShell.Run strCommandLine, 2, true\r\n  set WshShell = Nothing\r\n  Set objFSO = Nothing\r\n  Set objOutFile = Nothing\r\nEnd Sub\r\n\r\nFunction FindAvailableDriveLetter(strDirection)\r\n\r\n' The purpose of this function is to take the current drive letters, plus any reservations as per arrReservedLetters,\r\n' and return the next available drive letter from either direction as specified. This script is great for changing the\r\n' drive letter of CD\/DVD ROM drives, etc.\r\n' Based on an article by the Scripting Guy titled &quot;How Can I Determine the Next Available Drive Letter on a Computer?&quot;\r\n' found: http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jan05\/hey0122.mspx\r\n\r\n' Call this function by either of the two following methods.\r\n' strNewDriveLetter=FindAvailableDriveLetter(&quot;Descending&quot;)\r\n' strNewDriveLetter=FindAvailableDriveLetter(&quot;Ascending&quot;)\r\n\r\n  Dim arrReservedLetters, objDictionary, strComputer, objWMIService, colDisks, objDisk\r\n  Dim i, strDrive, intStart, intFinish, intStep\r\n\r\n  arrReservedLetters = Array(&quot;X:&quot;,&quot;I:&quot;,&quot;S:&quot;)\r\n\r\n  Set objDictionary = CreateObject(&quot;Scripting.Dictionary&quot;)\r\n\r\n  strComputer = &quot;.&quot;\r\n  Set objWMIService = GetObject(&quot;winmgmts:\\\\&quot; &amp; strComputer &amp; &quot;\\root\\cimv2&quot;)\r\n  Set colDisks = objWMIService.ExecQuery(&quot;Select * from Win32_LogicalDisk&quot;)\r\n  For Each objDisk in colDisks\r\n    objDictionary.Add objDisk.DeviceID, objDisk.DeviceID\r\n  Next\r\n\r\n' If the reserved drive letter(s) are already in-use, such as network drives already mapped when this script runs, this\r\n' process will fail with the error &quot;This key is already associated with an element of this collection&quot;, which is error\r\n' 457, so we need to use an &quot;On Error Resume Next&quot; to tell it to continue on errors.\r\n  For i = 0 to UBound(arrReservedLetters)\r\n    On Error Resume Next\r\n    wscript.echo &quot;Reserving drive letter &quot; &amp; arrReservedLetters(i)\r\n    objDictionary.Add arrReservedLetters(i), arrReservedLetters(i)\r\n    If Err.Number = 457 Then\r\n      wscript.echo &quot;Drive letter &quot; &amp; arrReservedLetters(i) &amp; &quot; has already been reserved because it's already in use.&quot;\r\n    ElseIf Err.Number &lt;&gt; 0 Then\r\n      wscript.echo Err.Description\r\n    End If\r\n    On Error Goto 0\r\n  Next\r\n\r\n' Note to understand this process 71 ASCII = CHAR G and 90 ASCII = CHAR Z\r\n  Select Case lcase(strDirection)\r\n    Case &quot;descending&quot;\r\n      intStart = 90\r\n      intFinish = 71\r\n      intStep = -1\r\n    Case &quot;ascending&quot;\r\n      intStart = 71\r\n      intFinish = 90\r\n      intStep = 1\r\n  End Select\r\n\r\n  For i = intStart to intFinish step intStep\r\n    strDrive = Chr(i) &amp; &quot;:&quot;\r\n    If objDictionary.Exists(strDrive) Then\r\n    Else\r\n'      Wscript.Echo strDrive &amp; &quot; is the next available drive letter.&quot;\r\n      FindAvailableDriveLetter = strDrive\r\n      Set objDictionary = Nothing\r\n      Set objWMIService = Nothing\r\n      Set colDisks = Nothing\r\n      Exit Function\r\n    End If\r\n  Next\r\n\r\n  Wscript.Echo &quot;There are no available drive letters on this computer.&quot;\r\n  Set objDictionary = Nothing\r\n  Set objWMIService = Nothing\r\n  Set colDisks = Nothing\r\n  wscript.quit(0)\r\n\r\nEnd Function\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Diskpart\u00a0may fail when creating more than one partition when executing the &#8220;assign letter=D&#8221; command. This is because Windows, WinPE included, by default assigns the first CD-ROM &#8220;type&#8221; drive to the first available letter after C:.\u00a0So if you are partitioning a new server, or repartitioning a server that contains only 1 partition (C:), the CD-ROM drive &#8230; <a title=\"Intelligently changing the drive letter assignment for multiple CD\/DVD ROM Drives\" class=\"read-more\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2008\/10\/19\/intelligently-changing-the-drive-letter-assignment-for-multiple-cddvd-rom-drives-42\" aria-label=\"Read more about Intelligently changing the drive letter assignment for multiple CD\/DVD ROM Drives\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[74,5],"tags":[76,421,78,77,75],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-diskpart","category-scripting","tag-assign-letterd","tag-diskpart","tag-diskpart-cd-rom","tag-diskpart-change-letter","tag-diskpart-fails"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/comments?post=42"}],"version-history":[{"count":11,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/42\/revisions"}],"predecessor-version":[{"id":43,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/42\/revisions\/43"}],"wp:attachment":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/media?parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/categories?post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/tags?post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}