Valerie Posted April 20, 2010 Posted April 20, 2010 The following script works as expected but I'd like an explanation of why the command CMD /C is necessary for it to run if the drive list contains drive a.This works:@echo offclssetlocalfor %%1 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 ( cmd /c if exist %%1:\ ( fsutil fsinfo drivetype %%1: ) )This hangs with a "no disk in drive" error message.@echo offclssetlocalfor %%1 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 %%1:\ ( fsutil fsinfo drivetype %%1: ) )
MrJinje Posted April 20, 2010 Posted April 20, 2010 (edited) I added some "ELSE" logic, give it a try.@echo offclssetlocalfor %i 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 %i:\ (fsutil fsinfo drivetype %i: )ELSE (fsutil fsinfo drivetype %i:))The CMD /C tells your script to give up when your if exist statement fails, which does not happen in your second script because it does not have a 'ELSE' block. /C Carries out My_Command and then terminates More Details Here and Here Edited April 20, 2010 by MrJinje
jaclaz Posted April 20, 2010 Posted April 20, 2010 Try reversing the logic of it.Fsutil does NOT throw an error if a drive is not accessible, BUT it will report an error message.In my Italian XP this error is "Directory principale non esistente"Thus this works:@ECHO OFFfor %%1 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 %%1: |FIND /V "Directory")jaclaz
Noise Posted April 20, 2010 Posted April 20, 2010 (edited) You can use DISKPART too, I feel it's a better tool for this type of thing:C:\> ECHO LIST VOL | DISKPART | FIND "NTFS"Volume 1 C System NTFS Partition 20 GB Healthy SystemReplace NTFS with CDFS to find the CDROM's. You'll have to do some parsing of the results, but this is cleaner and quicker than most methods. Edited April 20, 2010 by Noise
cluberti Posted April 20, 2010 Posted April 20, 2010 You could also get this incredibly easily with Win32_LogicalDisk from WMI and some vbscript:RunMeWithCscript()strComputer = "."Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")Set colDiskItems = objWMIService.ExecQuery( _ "SELECT * FROM Win32_LogicalDisk",,48) For Each objDiskItem in colDiskItems If objDiskItem.DriveType = 3 Then Wscript.Echo " Volume: " & objDiskItem.Caption Wscript.Echo " Drive Type: " & objDiskItem.Description Wscript.Echo " Compressed: " & objDiskItem.Compressed Wscript.Echo " File System: " & objDiskItem.FileSystem Wscript.Echo " Volume Size: " & FormatNumber(objDiskItem.Size/1024^3, 2) & " GB" Wscript.Echo " Free Space: " & FormatNumber(objDiskItem.FreeSpace/1024^3, 2) & " GB" Wscript.Echo " VolumeDirty: " & objDiskItem.VolumeDirty Wscript.Echo " VolumeSerialNumber: " & objDiskItem.VolumeSerialNumber Wscript.Echo "" End If If objDiskItem.DriveType = 5 Then Wscript.Echo " Volume: " & objDiskItem.Caption Wscript.Echo " Drive Type: " & objDiskItem.Description If Not objDiskItem.FileSystem = "" Then Wscript.Echo " File System: " & objDiskItem.FileSystem Wscript.Echo " Volume Size: " & FormatNumber(objDiskItem.Size/1024^3, 2) & " GB" Wscript.Echo " Free Space: " & FormatNumber(objDiskItem.FreeSpace/1024^3, 2) & " GB" End If Wscript.Echo "" End If If objDiskItem.DriveType = 2 Then Wscript.Echo " Volume: " & objDiskItem.Caption Wscript.Echo " Drive Type: " & objDiskItem.Description If Not objDiskItem.FileSystem = "" Then Wscript.Echo " File System: " & objDiskItem.FileSystem Wscript.Echo " Volume Size: " & FormatNumber(objDiskItem.Size/1024^3, 2) & " GB" Wscript.Echo " Free Space: " & FormatNumber(objDiskItem.FreeSpace/1024^3, 2) & " GB" End If Wscript.Echo "" End If Next '//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ '// Subroutine: RunMeWithCScript() '// '// Purpose: Forces the currently running script to use Cscript.exe as the Script '// engine. If the script is already running with cscript.exe the sub exits '// and continues the script. '// '// Sub Attempts to call the script with its original arguments. Arguments '// that contain a space will be wrapped in double quotes when the script '// calls itself again. To verify your command string you can echo out the '// scriptCommand variable. '// '// Usage: Add a call to this sub (RunMeWithCscript) to the beggining of your script '// to ensure that cscript.exe is used as the script engine. '//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public Sub RunMeWithCScript() Dim scriptEngine, engineFolder, Args, arg, scriptName, argString, scriptCommand scriptEngine = Ucase(Mid(Wscript.FullName,InstrRev(Wscript.FullName,"\")+1)) engineFolder = Left(Wscript.FullName,InstrRev(Wscript.FullName,"\")) argString = "" If scriptEngine = "WSCRIPT.EXE" Then Dim Shell : Set Shell = CreateObject("Wscript.Shell") Set Args = Wscript.Arguments For each arg in Args 'loop though argument array as a collection to rebuild argument string If instr(arg," ") > 0 Then arg = """" & arg & """" 'if the argument contains a space wrap it in double quotes argString = argString & " " & Arg Next 'Create a persistent command prompt for the cscript output window and call the script with its original arguments scriptCommand = "cmd.exe /k " & engineFolder & "cscript.exe """ & Wscript.ScriptFullName & """" & argString Shell.Run scriptCommand,,False Wscript.Quit Else Exit Sub 'Already Running with Cscript Exit this Subroutine End If End Sub
jaclaz Posted April 20, 2010 Posted April 20, 2010 Well, if order of columns is not a problem, a one-liner is possible at WMIC too:wmic.exe path Win32_Logicaldisk Get description^, nameTo change the order of the column is trickier that it might seem:@ECHO OFFSETLOCAL ENABLEDELAYEDEXPANSIONFOR /f "tokens=2,3 delims=," %%A IN ('wmic.exe path Win32_Logicaldisk Get name^, description /FORMAT:csv.xsl') DO (SET Tempvar=%%A,%%BFOR /F "tokens=1,2 delims=," %%C IN ('ECHO !TempVar!') DO ECHO %%D %%C)jaclaz
Yzöwl Posted April 20, 2010 Posted April 20, 2010 Well, if order of columns is not a problem, a one-liner is possible at WMIC too:wmic.exe path Win32_Logicaldisk Get description^, nameTo change the order of the column is trickier that it might seem:@ECHO OFFSETLOCAL ENABLEDELAYEDEXPANSIONFOR /f "tokens=2,3 delims=," %%A IN ('wmic.exe path Win32_Logicaldisk Get name^, description /FORMAT:csv.xsl') DO (SET Tempvar=%%A,%%BFOR /F "tokens=1,2 delims=," %%C IN ('ECHO !TempVar!') DO ECHO %%D %%C)jaclazOr:@FOR /F "TOKENS=* DELIMS=," %%# IN ('WMIC LOGICALDISK GET NAME^, DESCRIPTION^ /FORMAT:CSV^|FIND ":"') DO @FOR /F "TOKENS=2,3 DELIMS=," %%A IN ("%%#" ) DO @ECHO %%B %%A)
Valerie Posted April 20, 2010 Author Posted April 20, 2010 Cluberti - Yes, the script runs without error when Cmd /k is used.Thanks to all for your interest and responses.V.
cluberti Posted April 20, 2010 Posted April 20, 2010 Cluberti - Yes, the script runs without error when Cmd /k is used.Thanks to all for your interest and responses.V.That would mean indeed it's because the check for A is failing in fsutil, and using /C or /K causes a new cmd.exe process to spawn to do the check, which will return to the original cmd.exe to continue the next step in the loop regardless of whether or not the previous operation failed or not. Using cmd without switches means it runs the check in the same cmd.exe process, and thus the fsutil command being stuck will block the rest of the drive letters from being parsed. I would suggest using the vbscript I posted above, the wmic command from jaclaz or Yzowl if you must do this in a .cmd file, or make sure you call this with cmd /c or /k.
jaclaz Posted April 21, 2010 Posted April 21, 2010 That would mean indeed it's because the check for A is failing in fsutil, and using /C or /K causes a new cmd.exe process to spawn to do the check, which will return to the original cmd.exe to continue the next step in the loop regardless of whether or not the previous operation failed or not. Using cmd without switches means it runs the check in the same cmd.exe process, and thus the fsutil command being stuck will block the rest of the drive letters from being parsed. I would suggest using the vbscript I posted above, the wmic command from jaclaz or Yzowl if you must do this in a .cmd file, or make sure you call this with cmd /c or /k.Well, no, as said, it's not fsutil the problem, as it runs normally on non existing drives it's the "if exist" check.jaclaz
MrJinje Posted April 21, 2010 Posted April 21, 2010 (edited) it's not fsutil the problem, as it runs normally on non existing drives it's the "if exist" check.That is correct, if anyone looks at my post, the fix was to run FSUTIL during the else statement. for %i 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 %i:\ (fsutil fsinfo drivetype %i: )ELSE (fsutil fsinfo drivetype %i:)) Edited April 21, 2010 by MrJinje
jaclaz Posted April 21, 2010 Posted April 21, 2010 (edited) That is correct, if anyone looks at my post, the fix was to run FSUTIL during the else statement. Well, if anyone looks at my post , the if exist is NOT needed at all, the usual form of IF/THEN/ELSE is:IF <condition is true> THEN <do this> ELSE <do that>something like:IF <condition is true> THEN <do this> ELSE <do this>seems to me a little pointless, and all in all replaceable by:<do this> jaclaz Edited April 21, 2010 by jaclaz
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now