DarkShadows Posted June 30, 2005 Posted June 30, 2005 (edited) One problem in building our XPCDs is that we cannot know the CD-ROM's drive letter in advance. This is because we may have several hard drive partitions, optical drives, and other removable drives. Windows Setup Text Mode assigns it's own letters to these volumes. And from PC to PC the assigned letters will be different, based on a number factors: drive type; volume format; partition is active, primary, or extended; et. al.To counter this you may have seen many command script examples at this web site and others which include a routine to identify the CDROM drive letter. Most of these techniques rely on checking for the existence of a known file on the CD-ROM at each possible drive letter (checking all letters C through Z inside of a For-In-Do loop). There are also other variations on these technique (many you will see in this thread).But there are issues with such techniques:• The code is less modular. I prefer modular code so when I move to my next project, I copy and past modules from previous scripts to new ones. When you check for a specific file, folder, or volume label, then you must make damned sure it is actually on your XPCD, and you must also make damned sure it is not on any other drive that may be attached at the time you install from your XPCD. What happens when you rebuild your PC, but you leave your other HDD partitions intact? The For-In-Do Loop Checks search all drives looking for its check file/folder/label. Such a check doesn't stop once it has found the first instance. So if you have the same check file/folder/label in more than one drive, you will not get the correct drive letter assigned to the %CDROM% variable. • Even more critical is something that happens if you have more than one CD-ROM drive installed (which I do). A For-In-Do with a File/folder/volumename check searches all drives (C-Z), including a second CD drive that you may or may not have a CD in. It doesn't matter what these techniques are looking for, it is the very fact that they check every drive C-Z that causes the problem. Empty CD drives (and other drive types such as Iomega Rev) will cause errors when the Windows shell tries to check them for a file, or a label or whatever. Windows will put a dialog up on the screen and halt the installation until you respond:"'Windows No Disk' 'There is no disk in the drive. [Cancel] [Try Again] [Continue]" I personally find this problematic. In my opinion the behavior above just chopped the "Unattended " off of "Unattended Installation." I don't know about you, but I want code that allows me to stick in a XPCD and go work on something else while the PC installs itself. But, there is a much simpler technique provided by the Windows XP Command Prompt script language, if one is executing a command script from the CD-ROM itself (as opposed to first copying the script to the hard drive and executing it from there). Assuming you are using Windows XP, or later, you can use Batch Parameter Expansion (search for "Using batch parameters" in the Windows XP Help and Support Center). When any command script executes, its first parameter, %0, equals the command script file name. However using parameter expansion, we can derive the CD-ROM drive letter from %0 by using: %~d0.For a simple practical example, simply copy the code below and paste it into a command file and execute it:@Echo OFFSetLocal enableextensionsCLSEcho.Echo I am file (not yet expanded): %0Echo My Expanded File Name: %~n0Echo My Expanded Extension: %~x0Echo My Expanded Name and Extension: %~nx0Echo My Expanded Drive: %~d0Echo The Expanded Root of My Drive: %~d0\Echo Some Other Expanded Path on My Drive: %~d0\SomeOtherPathEcho My Expanded Path: %~p0Echo My Expanded Drive and Path: %~dp0Echo.PauseEndLocalGoTo :EOFLike Yzöwl states below for Windows 2000, the Endlocal, and Goto:EOF at the end are not strictly required (but they are great programming structure). There is always one implicit EndLocal at the end of each command script in Windows XP. However, if you nest Setlocals, you should definitely use matching EndLocal statements.While undocumented in the Windows XP Help and Support Center (surprise ), testing reveals that command extensions also NEED to be enabled in Windows XP for batch parameter expansion to work (but they are enabled by default in XP). There are two methods available to enable command extensions. One is to use:SetLocal enableextensions The other is to start your command script with the following command:Cmd /e:on ScriptName.cmd the code above to shows the first method.This technique allows you programmatically account for differing CD/DVD-ROM drive letters from PC to PC. It only works because the command script resides on the CD-ROM drive. If you move the script above to another volume, you will get different values. To illustrate, copy the sample script above to different volumes and execute it from each--all the values above that use the d modifier will change. You cannot manipulate batch parameters in the same manner that you can manipulate environment variables. You cannot search and replace values or examine substrings. However, you can assign the parameter to an environment variable, and then manipulate the environment variable.What makes the technique so powerful is that it doesn't require a check file, folder, or label. It doesn't care how many drives you have--it's not looking for any of them. When any script withSet CDROM=%~d0in it runs from the CD/DVD drive your XPCD is in, it will automatically and programmatically know the CD-ROM drive letter. It's just so much simpler to type, takes less time to execute, and is much less problematic. All the upside in the world, and no downside.[Edit: 2005-09-22]Since I've received questions about this original topic offline, I've decided to create and share a script people can plug into their XPCDs that solves all ambiguity as to how this technique should be employed. It is tested on Windows XP, and should work as well on Windows 2000. Download the .zip file, extract it, open the .cmd and read it. It should explain everything in sufficient detail. Post any questions to this thread.Variables set in any script launched from CmdLines.txt do not live past the life of that script. MapCD must be called from the top of each script launched from CmdLines.txt, as %CDROM% will destroyed after each script called from CmdLines.txt ends.[/Edit: 2005-09-22][Edit: 2005-09-23]MakeMapCD.zipCurrent Version: v1.1.1Changes from v1.1 are mostly organizational and documentation. The original version I posted (v1.1) will still work just fine, so long as MapCD is called from the top of any of your scripts (which was my recommendation all along). [/Edit: 2005-09-23]Hope you find this useful! B)If you have a script tip or trick that applies to unattended XPCDs post it to this thread.Keywords: CD CD-ROM DVD DVD-ROM drive drives letter letters find locate assign obtain acquire get set %CDROM% unattended installation XPCD windows xp 2000 batch command script tip tips trick tricks technique techniques Edited September 30, 2005 by DarkShadows
Yzöwl Posted June 30, 2005 Posted June 30, 2005 (edited) For win2k just start the batch with@echo offsetlocal enableextensionsyou should end it withendlocalgoto :eofcorrect but not strictly necessary<Edit>I've added a couple of extras to this one, there are other combinations though@echo offsetlocal enableextensionsclsecho.echo I am file (not yet expanded): %0echo My Expanded File Name: %~n0echo My Expanded Extension: %~x0echo My Expanded Name and Extension: %~nx0echo My Expanded Drive: %~d0echo The Expanded Root of My Drive: %~d0\echo Some Other Expanded Path on My Drive: %~d0\SomeOtherPathecho My Expanded Path: %~p0echo My Expanded Drive and Path: %~dp0echo My Expanded full filename and path %~f0echo My Expanded short filename path %~dps0echo.pauseendlocalgoto :eof</Edit><Edit2>Although not related to XPCDs, this one gives you a nice little example using the above@echo off&setlocal enableextensionsmd "%~dp0test"copy %0 "%~dp0test"del %0Put this one on your Desktop naming it test.cmd, double click it, and keep your eyes on it at the same time.</Edit2> Edited June 30, 2005 by Yzöwl
Vadikan Posted June 30, 2005 Posted June 30, 2005 I beleive the uA guide should have SET CDROM=%~d0 in the RunOnceEx from CD article as an addition (but not replacement) to the current script.
Gee Posted June 30, 2005 Posted June 30, 2005 (edited) Is there a reason why you haveSetLocal enableextensions@Echo OFFinstead of@Echo OFFSetLocal enableextensionsIt should make a difference, but your method will echo that first line. Edited June 30, 2005 by Gee
clavicle Posted June 30, 2005 Posted June 30, 2005 Superb! @DarkShadows, your effort is really appreciable! The guide is really great especially for persons like me who keep hunting for sources here and there. Good job!
DarkShadows Posted June 30, 2005 Author Posted June 30, 2005 Is there a reason why you haveSetLocal enableextensions@Echo OFFinstead of@Echo OFFSetLocal enableextensionsIt should make a difference, but your method will echo that first line.<{POST_SNAPBACK}> Whoops! Thanks for pointing that out! I'll edit the first post accordinglySuperb! @DarkShadows, your effort is really appreciable! The guide is really great especially for persons like me who keep hunting for sources here and there. Good job! <{POST_SNAPBACK}>Thank you. Glad it helps.Nooooo! All my secrets! Published for all to see!<{POST_SNAPBACK}> Sorry Nois3! But for a small ransom, I won't reveal your secret identity, nor the location of your hideout!
gunsmokingman Posted June 30, 2005 Posted June 30, 2005 Please do not let the size of this bother you almost 1/3 of the lines are for asking if you want to keep or delete the the file.This is not a batch file but a VBS script it will list all instances of a file named win51ip regardless of extention. Save This As Seekwin51ip.vbsRed Is The Question To Either keep Or Delete The File. This Can Be Removed From The Script Green Is The File It Searches ForDim Act : Set Act = CreateObject("Wscript.shell") Sd = Act.ExpandEnvironmentStrings("%systemdrive%") UN = Act.ExpandEnvironmentStrings("%UserName%") Dim StrComputer, Tfile TFile = (Sd & "\TempList.txt") strComputer = "." Function Search_File Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colFiles = objWMIService.ExecQuery("Select * from CIM_DataFile Where FileName = 'win51ip'") If colFiles.Count = 0 Then Act.Popup "No File Exists With That Name", 3,"Gsm No File", 0 + 32 '''' If The File Is Not There Exit Function End If Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(Tfile) '''' The Text File That It Makes For Each objFile in colFiles Kbname = Ucase(objFile.FileName & "." & objFile.Extension) '''' Makes The Whole File Name In Upper Case KbPath = UCase(objFile.Drive & objFile.Path) '''' Makes The Whole Path To File In Upper Case TheFile = KbPath & Kbname '''' This Makes The Full Path And File Name And Extention Line1 ="=========================================" objTextFile.Write( Line1 & "{File Name And Location}" & Line1 & vbCrlf & vbcrlf & Kbpath & Kbname & vbCrLf & Vbcrlf) Next objTextFile.Close Act.Popup "Completed The Search", 3, "Gsm Search File", 0 + 32 Act.Run(Sd & "\TempList.txt"),1,True '''' Ask If You Want To keep Or Delete The File Question = Act.popup(_ Un & VbCrlf & "Did You want To Keep The " & Tfile & VbCrlf & "Yes To Keep The File" &_ VbCrlf & "No To Delete The File" & VbCrlf & "If Nothing Is Selected After 15 Seconds Then" &_ VbCrlf & "It Will Delete The File", 15, "Gsm Keep Or Delete", 4 + 32) If Question = 6 Then Exit Function End If If Question = 7 Then ObjFSO.DeleteFile(Sd & "\TempList.txt") Exit Function End If If Question = -1 Then ObjFSO.DeleteFile(Sd & "\TempList.txt") Exit Function End If End Function Search_FileAnd This One Is Where You Type The Name Of The file You Would Like To Search For. Save As UserSeekFile.vbsPurple Is The User Input That Get The Name, Plus A Part That deal With Quiting And Continuing On with The script.Red Is The Question To Either keep Or Delete The File. This Can Be Removed From The Script Dim Act : Set Act = CreateObject("Wscript.shell") Sd = Act.ExpandEnvironmentStrings("%systemdrive%") UN = Act.ExpandEnvironmentStrings("%UserName%") Dim FName, StrComputer, Tfile TFile = (Sd & "\TempList.txt") strComputer = "." Function Search_File UserIn = Inputbox(Un & VbCrlf & "Type In The Name Of The File You would Like To Search For." & VbCrlf & "This Does Not Need Any Extention, Adding The Extention Will Cause A False Search Result","Gsm Name The File","") If UserIn <> "" Then Else Gsm1 = Act.popup (Un & VbCrlf & "This Needs A Name To Complete The Search" & VbCrlf & Un & " Did You Want To Quit Or Continue?" & VbCrlf & "Yes To Continue" & VbCrlf & "No To Exit" & VbCrlf & "After 30 Seconds This Will Exit", 30,"Gsm Continue Or Quit", 4 + 64) If Gsm1 = 6 Then Search_File Else If Gsm1 = 7 Then Wscript.quit Exit Function End If If Gsm1 = -1 Then Wscript.quit Exit Function End If End If End If FName = UserIn Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colFiles = objWMIService.ExecQuery("Select * from CIM_DataFile Where FileName = '" & FName & "'") If colFiles.Count = 0 Then Act.Popup "No File Exists With That Name", 3,"Gsm No File", 0 + 32 '''' If The File Is Not There Exit Function End If Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(Tfile) '''' The Text File That It Makes For Each objFile in colFiles Kbname = Ucase(objFile.FileName & "." & objFile.Extension) '''' Makes The Whole File Name In Upper Case KbPath = UCase(objFile.Drive & objFile.Path) '''' Makes The Whole Path To File In Upper Case TheFile = KbPath & Kbname '''' This Makes The Full Path And File Name And Extention Line1 ="=========================================" objTextFile.Write( Line1 & "{File Name And Location}" & Line1 & vbCrlf & vbcrlf & Kbpath & Kbname & vbCrLf & Vbcrlf) Next objTextFile.Close Act.Popup "Completed The Search", 3, "Gsm Search File", 0 + 32 Act.Run(Sd & "\TempList.txt"),1,True '''' Ask If You Want To keep Or Delete The File Question = Act.popup(_ Un & VbCrlf & "Did You want To Keep The " & Tfile & VbCrlf & "Yes To Keep The File" &_ VbCrlf & "No To Delete The File" & VbCrlf & "If Nothing Is Selected After 15 Seconds Then" &_ VbCrlf & "It Will Delete The File", 15, "Gsm Keep Or Delete", 4 + 32) If Question = 6 Then Exit Function End If If Question = 7 Then ObjFSO.DeleteFile(Sd & "\TempList.txt") Exit Function End If If Question = -1 Then ObjFSO.DeleteFile(Sd & "\TempList.txt") Exit Function End If End Function Search_File
Ghost82 Posted June 30, 2005 Posted June 30, 2005 Nice!!!I found some more info while searching with Google , check these links:http://labmice.techtarget.com/articles/batchcmds.htm
n7Epsilon Posted June 30, 2005 Posted June 30, 2005 GREAT WORK !!!! --> That saves me the hassle of coding my brains out to derive the Windows XP source path from the registry during setup !!!!!Thanks, so simple and so unthinkable !!!(NB: Using this method is better in RunOnceEx, as this method guarantees that the batch file will always correctly set the source path of the Windows source!! regardless of whether the source is on the CD-ROM or on a folder on the hard drive !!!!)(*** runs off to Notepad2 to edit RunOnceEx.cmd code...)...
Martin Zugec Posted June 30, 2005 Posted June 30, 2005 I am using this for my UNC based installations... Which is quite good way. When I wanted to detect CDROM drive, I am using different method than most people here - my solution is based on cd name. E.g. find drive, where name is "Unattended installation" and set it as source (using WMI classes)
gunsmokingman Posted June 30, 2005 Posted June 30, 2005 I found this code on Microsoft this does not need a check file and willlist the Cd DriveJust For Drive LetterstrComputer = "."Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")Set colItems = objWMIService.ExecQuery("Select * from Win32_CDROMDrive")For Each objItem in colItems CreateObject("Wscript.Shell").Popup "Your Cd Is" & vbCrLf & objItem.Drive & "\" , 4, "Cd = " & objItem.Drive , 0 + 32NextThis One I Made Based On The Above Script It Checks To See If XP Is In The CDROM Blue Is The Part Of The Script That Checks To See If A XP In The CDROMGreen Is The Cd Varible And File It Checks ForDim strComputer : strComputer = "." Dim Act : Set Act = CreateObject("Wscript.Shell") Dim Fso : Set Fso = CreateObject("Scripting.FileSystemObject") Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_CDROMDrive") For Each objItem in colItems Dim Cd : Cd = objItem.Drive Next If Fso.FileExists(CD & "\i386\winnt32.exe") Then Act.Popup "This Is The Correct Cd" & vbCrLf & CD & "\i386\winnt32.exe", 5, CD & " Confirm" Else If Not Fso.FileExists(CD & "\i386\winnt32.exe") Then Act.Popup "This File Was Missing" & vbCrLf & CD & "\i386\winnt32.exe", 5, CD & " Missing" End If End If
Yzöwl Posted June 30, 2005 Posted June 30, 2005 This one is for Windows XPIt will tell you your CD-Drive letter(s), without the needing any disk in it@echo offfor %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do ( fsutil fsinfo drivetype %%a:|find "CD-ROM">nul 2>&1&&echo/%%a:)pause&goto :eof
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now