Batch files: First Free Drive
Batch Files: Snippets 1 | First Free Drive |
Batch file code snippets. |
These code snippets are my thoughts on automatic available drive detection; final code is destined for the mini-servers to prevent conflicts.
Batch file to detect first free drive letter
Every drive has a hidden nul file associated with it, this can be used to determine a drives existence.
For example if exist h:\nul echo. Disk in use -- If the nul file exists on drive "h" output disk in use.
:: Test folder exists cls @echo off set w=s if exist e:\nul echo. Disk in use for %%p 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 if exist %%p:\nul echo. %%p Disk in use for %%p 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 if not exist %%p:\nul echo. %%p Disk is available for %%p 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 if not exist %%p:\nul set w=%%p echo. echo Drive to use %w% PAUSE
The above code has been on the back burner for some time. It suffers from the fact unless a drive contains some media it is not registered as being in use.
Drive A and B are rightly detected as being free however I would consider it undesirable to assigned these using SUBST. Bound to cause conflicts on older machines that have these drives installed. (BIOS also assumes these are still used) Wonder what these legacy drives will be used for!
Real problem with the above code is lack of CD detection. Default for a CD (DVD) is drive D however more than one device may be installed even worst CD’s may be remapped to a different drive letters.
I found some horrific code to detect CD drives hence the back burner. The above code is useful, remove letters a, b and any CD drives that exist, use the “for” loop to scan for free drive letter (reverse letters to find first free drive). Backwards-compatible OS 95.
Disk Start.vbs automatic drive detection
I noticed on the forum Marshy had found a bug in “Disk Start.vbs after applying his correction to get the database start stop correctly working I thought why not hack this code some more.
I spent two evenings at several sites learning some Vbscript, hacked the code to automatically detect the first free drive letter.
|
Variable letter is assigned a numeric value starting with "c" drive. Note 1: I have not included A or B drives because I believe these will cause problems as mentioned above. Within the while loop the variable letter is incremented to the next drive letter. This new value is checked the while loop repeats until a drive does not exist. Note 2: DriveExists requires a drive letter with a colon hence the need to build a string. While loop exit, variable letter contains first free drive letter. Drive numeric is converted to a character which in turn is converted to upper case using: UCASE(Chr(letter)) Note 3: I think lower case drive letters are safe to use however I have always used uppercase. What really is neat about this code it requires no additional instructions to detect CD drives. Note 4: This script passes incorrect variables to Server_Start.bat in addition %2 is not checked hence will not work. Check this page for a solution: Known bugs |
Summary 1
After two evenings work I looked at that elegant code and it really annoyed me! I could not achieve that using a batch file.
My next quest how do you communicate between these two scripts; an easy answer is to use an intermediary write and read to and from a file. The bat would run vb, which creates a file and write data to it, bat would read this file’s data and then delete the file.
A drive letter by any stretch of the imagination is not a large amount of data and does not warrant an intermediary file. So how do you pass variables? How compatible with older kit would this be? Hey! Just had a thought how compatible will it be with newer kit.
An interesting dilemma, VBscripts fire up security warnings, “Malicious script detected” well that rattles my cage thought I wrote better code than that!
An intermediary file
These two alternative batch files produce identical results however they suffer from being Windows 2000 and XP specific. They both use extended batch commands (FOR /F and SET /P).
|
| ||||
|
This script creates and writes to a file. As expected fires up security, |
Error code - Alternative
It is possible to pass numeric values using the errorlevel variable.
|
|
The above looks promising, uses standard batch file code and the vb scripts does not change any system stuff hence no security alert.
cscript.exe and for loop alternative
I am interested in passing a text string and not a numeric this solution achieves that.
The following file cscript.exe (or WScript.exe included with XP) can read and execute scripts the output is directed to either command window or stdout. Running vb script with cscript.exe any values echoed by the script can be read within the batch file using a for loop and f switch.
|
|
It uses extended batch command (For /F) however no security alerts produced by vbs because it outputs to stdio.
Ref: http://www.tomshardware.com/ucg/commands/cscript-13412.html (cscript - Windows 98/ME, 2000, XP)
Summary 2
Of the solutions only one looks backward compatible with older OS’s I suppose the real question is when was vb script introduced.
It looks as if VBScript is usable on 98! The For /F is Windows 2000 and XP specific. Using a modified version of 4) means the script will be backwards compatible to 98. What will Vista do with it?
Proposed solution - 1
It’s a long-winded approach suppose how far back you need to go.
|
|
Proposed solution - 2
Even more long-winded however it does go back to year dot. Interestingly it has one advantage it picks up a CD or DV drive without the need for media being inserted as in Batch file to detect first free drive letter
|
Summary 3
After completing (16-4-2008) the above write-up again left it on the back burner because the proposed solutions were far from elegant. Three months later discovered a real solution was staring me in the face take the very first piece of code and combine it with Proposed solution - 2.
Final Solution
The for loop selects each drive letter in turn, CD (change drive) attempts to force a drive to be currently selected. An error is produced if the drive is unavailable (free) and that letter is assigned to the variable freedrive. Drives are scanned in reverse order hence the last drive assigned becomes the first available.
@echo off for %%a in (Z Y X W V U T S R Q P O N M L K J I H G F E D C) do CD %%a: 1>> nul 2>&1 & if errorlevel 1 set freedrive=%%a: echo %freedrive% pause
The solution to this problem of auto-drive detection was always destined for a new range of mini-servers now published. To my horror discovered the above failed on XP but worked fine on Vista. The failure mode was interesting, drive letter was allocated and servers worked fine plug in a USB stick, its detected with no problem however the drive letter allocated was the same as auto-detection. Servers continued to work USB stick was not accessible. After stopping the servers USB drive letter registered and drive was accessible.
Strictly speaking not a failure from the server’s point of view just inconvenient to a user. Solution implemented on the mini-servers was to reverse drive letter detection hence first allocated if free is Z.
@echo off for %%a in (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 CD %%a: 1>> nul 2>&1 & if errorlevel 1 set freedrive=%%a: echo %freedrive% pause
Conclusion
Looks like several solutions are possible it’s a bit of pick and mix, suppose it depends on the requirements.
Ric |