Jump to content

Need help "For" batch command


Recommended Posts

Hi everyone!

First I'm sorry for my bad English.

 

I'm new with DOS also batch command so I create this topic to get some advices from you.

 

I want to create a .bat file, which using imdisk to mount ISO file to virtual drive. (this .bat run on WinPE)

 

It something like this

set /p type=Type a letter:REM now run imdiskimdisk -a -f %isofile% %type%:

with %isofile% is ToolsforPE.ISO (put on root of any partition)

 

I got 2 problems

 

1st:  detect if %type% is a CD/DVD drive, because imdisk cannot mount ISO to here.

2nd:  detect where %isofile%

 

I try this command to solved 1st problem

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 (fsutil.exe fsinfo drivetype %%a:|find "CD-ROM">nul&&set cdletter=%%a)echo CD-ROM drive letter is %cdrom%

Real CD-ROM drive letter from my desktop is F:

But if run it from WinPE with an ISO file already mounted to such as Y:, then above command will return cdrom is Y:

What about my F: letter ?

 

I try this command to solved 2nd problem

for %%b 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 (dir %%b:\ToolsforPE.ISO >nul 2>nul && (set isofile=%%b:\ToolsforPE.ISOgoto :runimdisk)echo ISO not foundbla ...

Still above problem, if we have 2 ISO with same name, put to root of 2 partition, then above command will set isofile to the first found. I want to improve .bat, it will print some text say that there are 2 ISO found, and ask user pick one to mount.

 

Also I need another .bat to detect Microsoft EFI Partition, since EFI par does not have a letter, then I cannot use dir %%a:\efi or some thing like that.

 

And I'm sorry, because I don't want to create another topic just ask for .bat file which can detect EFI par, I think my 3 problems are same and can put to one topic.

 

Thanks.

 

Edit:

P/s: I found some hint from internet say using wmic to get CD drive, but I found that, some rebuild versions of WinPE, wmic does not exist, so I try fsutil instead.

Edited by congnt92
  • Upvote 1
Link to comment
Share on other sites


Perhaps a VBS script would be better suited to your needs, here is an example of looping threw all the non empty drives.

 

'-> Object For RuntimeDim Fso :Set Fso = CreateObject("Scripting.FileSystemObject")'-> Varibles For Run TimeDim Drv, Dsk'-> Loop Threw All Drives   For Each Dsk In Fso.Drives      If Dsk.IsReady Then'-> Drive Type       Select Case Dsk.DriveType            Case 0: Drv = "Unknown"      Case 1: Drv = "Removable"      Case 2: Drv = "Fixed"      Case 3: Drv = "Network"      Case 4: Drv = "CD-ROM"      Case 5: Drv = "RAM Disk"          End select          WScript.Echo Dsk.DriveLetter & ":\ " & Drv      End If     Next 
  • Upvote 2
Link to comment
Share on other sites

Perhaps a VBS script would be better suited to your needs, here is an example of looping threw all the non empty drives.

 

'-> Object For RuntimeDim Fso :Set Fso = CreateObject("Scripting.FileSystemObject")'-> Varibles For Run TimeDim Drv, Dsk'-> Loop Threw All Drives   For Each Dsk In Fso.Drives      If Dsk.IsReady Then'-> Drive Type       Select Case Dsk.DriveType            Case 0: Drv = "Unknown"      Case 1: Drv = "Removable"      Case 2: Drv = "Fixed"      Case 3: Drv = "Network"      Case 4: Drv = "CD-ROM"      Case 5: Drv = "RAM Disk"          End select          WScript.Echo Dsk.DriveLetter & ":\ " & Drv      End If     Next 

Tks for your help, gunsmokingman.

I want to use .bat file because I just need a .bat to do all task.

With this .bat, that say loadiso.bat, I can:

- Find and detect path of ISO then set to var1

- Allow user choose a drive letter then set to var2

- Check if var2 is a free drive letter or already in use (by

dir %var2%:

command), then if user choose a "free" drive letter, run imdisk mount var1 to var2

But I found that, if a drive letter is CDROM with not insert a CD, dir %var% will return that var2 is a free drive letter. So I must check drive letter of CDROM first, set it to var3, then if %var2%==%var3% >> echo can not use this drive letter, it is CDROM ....

 

BUT now, I think that may using .bat to detect if there are more than 1 ISO file from root directory quite difficult, also using .bat to detect CDROM drive letter is quite difficult. So I will give up.

I found that this command will show letters which alreary in use. Very simple, very quickly

 

fsutil fsinfo drives

 

 

Then if user choose a letter which exist from above list, .bat will echo %var2% is already use. And it always work because I found that any rebuild version of WinPE exist fsutil.exe.

 

But I got another problems.

 

On Mini Windows XP, fsutil fsinfo drives resturn result which C:\ D:\ E:\ F:\ with NUL between them.

On Win7/8, it return C:\ D:\ E:\ F:\ with space betwwen them.

How can I use for /f command ???

for /f what token and what delims %%i in (A B C D E F G H ... Z) do set list=%%i

to output:

echo NOTE: ISO file can NOT be mounted to %list%:

Tks

Edited by congnt92
  • Upvote 1
Link to comment
Share on other sites

Maybe you should start with getting the notion that batch files on Windows NT systems are NOT "Dos" batches (and BTW it would be smart to use NOT the .bat extension but rather the .cmd one).

 

The detection of CD-Rom drive letter is not a "new" problem, there are several examples on the board, a same CD-ROM drive may (obviously) get a different drive letter in different environments, the assigning of the Y: to the CD-ROM drive is most probably something "specific to your PE build.

Something *like* this:

SETLOCAL ENABLEDELAYED EXPANSIONSET /A Counter=1for %%b 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 (dir %%b:\ToolsforPE.ISO >nul 2>nul && (set isofile[!Counter!]=%%b:\ToolsforPE.ISO&&SET /A Counter+=1)IF NOT DEFINED isofile[1] echo ISO not foundbla ...

Will put in isofile[1], isofile[2}, etc. all instances found.

 

About the list, this works on XP (and may work on 7/8 as well :dubbio:):

@ECHO OFFSETLOCAL ENABLEDELAYEDEXPANSIONSET list=FOR /F "tokens=*" %%A IN ('FSUTIL FSINFO DRIVES ^| FIND ":"') DO SET list=!list! %%AFOR /F "tokens=2,* delims= " %%A IN ('ECHO %list%') DO SET list=%%A %%BSET list

jaclaz

  • Upvote 2
Link to comment
Share on other sites

Maybe you should start with getting the notion that batch files on Windows NT systems are NOT "Dos" batches (and BTW it would be smart to use NOT the .bat extension but rather the .cmd one).

 

The detection of CD-Rom drive letter is not a "new" problem, there are several examples on the board, a same CD-ROM drive may (obviously) get a different drive letter in different environments, the assigning of the Y: to the CD-ROM drive is most probably something "specific to your PE build.

Something *like* this:

SETLOCAL ENABLEDELAYED EXPANSIONSET /A Counter=1for %%b 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 (dir %%b:\ToolsforPE.ISO >nul 2>nul && (set isofile[!Counter!]=%%b:\ToolsforPE.ISO&&SET /A Counter+=1)IF NOT DEFINED isofile[1] echo ISO not foundbla ...

Will put in isofile[1], isofile[2}, etc. all instances found.

 

About the list, this works on XP (and may work on 7/8 as well :dubbio:):

@ECHO OFFSETLOCAL ENABLEDELAYEDEXPANSIONSET list=FOR /F "tokens=*" %%A IN ('FSUTIL FSINFO DRIVES ^| FIND ":"') DO SET list=!list! %%AFOR /F "tokens=2,* delims= " %%A IN ('ECHO %list%') DO SET list=%%A %%BSET list

jaclaz

 

Tks for your help Jaclaz, I will try your code when I come back home.

 

Just a quetion, Can you explain what diffrence between .bat and .cmd. You mean, if I want to create a "batch" file which run from within windows, then I should use .cmd extension, right?

 

And I'm sorry for any inconvenience caused to you, But since you're master of .bat code, can you visit this topic and help me :thumbup

Edited by congnt92
  • Upvote 1
Link to comment
Share on other sites

It is just a "safety" measure (and to use some consistency).

There is no real difference on a modern, recent system, the same batch script will run the same as either .bat or as .cmd.

In theory a .bat should be associated to command.com (and it would be an actual "dos" batch), whilst a .cmd should be associated to cmd.exe (and it would be a NT batch, NOT a "dos" one, on all NT systems when you open the command prompt or the command window you are NOT running dos, you are running the NT command interpreter).

But if you use batches on different OS's you might need to put in them checks to make sure they run on the "right" OS or "refuse" to run on a non-expected OS.

If you name a NT batch as .cmd it will NOT run on DOS (MS-DOS or FreeDOS, etc.) and on 9x/Me.

 

jaclaz

  • Upvote 2
Link to comment
Share on other sites

It is just a "safety" measure (and to use some consistency).

There is no real difference on a modern, recent system, the same batch script will run the same as either .bat or as .cmd.

In theory a .bat should be associated to command.com (and it would be an actual "dos" batch), whilst a .cmd should be associated to cmd.exe (and it would be a NT batch, NOT a "dos" one, on all NT systems when you open the command prompt or the command window you are NOT running dos, you are running the NT command interpreter).

But if you use batches on different OS's you might need to put in them checks to make sure they run on the "right" OS or "refuse" to run on a non-expected OS.

If you name a NT batch as .cmd it will NOT run on DOS (MS-DOS or FreeDOS, etc.) and on 9x/Me.

 

jaclaz

 

Many thanks for your clarification, Jaclaz.

I only use this .bat to mound ISO file when boot to WinPE or LiveXP. And I got problems with fsutil fsinfo drives only with LiveXP cmd. (as I report above). But I think your .bat code solved my problem (I will report as I can test it).

 

By using fsutil, I do not need to check if a letter drive is CD/DVD. But as you say

The detection of CD-Rom drive letter is not a "new" problem

 

 so can you give me some link

 

And it's not specific to my PE build. On my real Windows, I got this problems too.

 I have a real CD/DVD with F: drive letter, and a virtual CD/DVD with G: (after install UltraISO). And if use

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 (fsutil.exe fsinfo drivetype %%a:|find "CD-ROM">nul&&set cdletter=%%a)echo CD-ROM drive letter is %cdrom%

then it return CD-ROM drive letter is H. In winPE, if an ISO file was mounted to such as Y:, then it return Y, not F, or not both F and Y.

 

- I found from your code some special characters. such as ! [ ] in variable, can you give me some links about these? Tks

  • Upvote 1
Link to comment
Share on other sites

- I found from your code some special characters. such as ! [ ] in variable, can you give me some links about these? Tks

The [] are not "special" at all, they are just a separator, the ! is a basic part of NT batches, to use DelayedExpansion:

http://www.robvanderwoude.com/variableexpansion.php

 

And it's not specific to my PE build. On my real Windows, I got this problems too.

I have a real CD/DVD with F: drive letter, and a virtual CD/DVD with G: (after install UltraISO). And if use ...

I really cannot understand the question/problem. :unsure:

Drive letter assignment is NOT carved in stone, every Operating System will assign (or not assign) a given drive letter to a given device or volume along some "rules" or "settings" that are specific to the booted environment, no surprise that a same device or volume will get assigned a different drive letter in different environments.

Your code is "botched", however, if you have more than one CD-ROM devices and you want to detect them all:

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 (

fsutil.exe fsinfo drivetype %%a:|find "CD-ROM">nul&&set cdletter=%%a

)

echo CD-ROM drive letter is %cdrom%

 

of course that batch will return a single drive letter for the CD-rom, the LAST CD-ROM device found.

Also since you are looking for the drive letter, you should NOT loop through all the drive letters as it will be MUCH slower, loop only through the actually Mounted ones, this will be faster:

SET cdletter=FOR /F %%A in ('MOUNTVOL^|FIND ":\"') DO (fsutil.exe fsinfo drivetype %%A|find "CD-ROM">nul&&set cdletter=!cdletter! %%A)ECHO CD-ROM drive letter(s) is/are %cdletter%

But still there are much faster ways than fsutil fsinfo drivetype to find out if a device is a CD-ROM, *like*:

For /F "tokens=3,5 delims=\ " %%A IN ('REG QUERY HKLM\SYSTEM\MountedDevices /s ^|FIND "\DosDevices\" ^| FIND "4300640052006F006D"') DO set CDROM=!CDROM! %%ASET CDROM

jaclaz

  • Upvote 2
Link to comment
Share on other sites

#1: I'm at home now and very happy to say that your code work very very perfect.

But it return how many ISO found, how can I output path of each iso was found by .bat too ?

 

#2: Again, just want to say tks to you.

 

Run your code from LiveXP, fsutil with nul in output result now is not problems.

But how can I improve it, instead of A:\ B:\ ... I only need A: B: ...

 

#3

Oh, my bad.

of course that batch will return a single drive letter for the CD-rom, the LAST CD-ROM device found.

 

 

The diffrences between yours and mine is

set cdletter=!cdletter! %%A

And you right, no need to looking for the drive letter. But not luckily, LiveXP i'm using does not exist moutvol.

 

But when i run your code, it return

CD-ROM drive letter is !cdletter! h

  (H is right, but it is virtual CD, the real one is F)

 

 

#4 Run

For /F "tokens=3,5 delims=\ " %%A IN ('REG QUERY HKLM\SYSTEM\MountedDevices /s ^|FIND "\DosDevices\" ^| FIND "4300640052006F006D"') DO set CDROM=!CDROM! %%ASET CDROM

returns

CDROM=!CDROM! REG_BINARY

just copy yours and paste to notepad, do not know why it does not work. Tks

  • Upvote 1
Link to comment
Share on other sites

You need to use ENABLEDELAYEDEXPANSION to resolve variables like !CDROM!, you have already been told this, and you have been ALREADY told to READ here:

http://www.robvanderwoude.com/variableexpansion.php

you need to study and understand the syntax of batch files, Delayed Expansion is something that you must become familiar with.

 

But how can I improve it, instead of A:\ B:\ ... I only need A: B: ...

Then strip them, the idea is that you are given some examples, they are intended to be used as a way to learn batch syntax, not that of writing the batch for you, not even snippet by snippet.

However, what do you think would be the effect of:

SET cdletter=%cdletter:\=%

How will the value of cdletter be affected?

just copy yours and paste to notepad, do not know why it does not work. Tks

Sometimes copy and paste (it depends on the browser, the board software, etc.) may transform Tabulators in spaces, the delims in:

"tokens=3,5 delims=\ "

are intended to be \ (backslash) and Tabulator (not space).

 

jaclaz

  • Upvote 2
Link to comment
Share on other sites

However, what do you think would be the effect of:

SET cdletter=%cdletter:\=%

 

Never better. :thumbup

 

Then strip them ... not that of writing the batch for you

 

 Well, i'm sorry. Because i'm new with batch command then just want to ask you to make sure.

Before ask you again, i try with this command (base on yours) but it not work properly

 

Yours

@ECHO OFFSETLOCAL ENABLEDELAYEDEXPANSIONSET list=FOR /F "tokens=*" %%A IN ('FSUTIL FSINFO DRIVES ^| FIND ":"') DO SET list=!list! %%AFOR /F "tokens=2,* delims= " %%A IN ('ECHO %list%') DO SET list=%%A %%B

return: C:\ D:\ E:\ ..

I add this line

FOR /F "tokens=2,* delims=\ " %%A IN ('ECHO %list%') DO SET list=%%A %%B

 

but it return C: D:\ E:\  (D, E not work and i'm not good at .bat to know why)

and then i ask you to get your help.

 

For /F "tokens=3,5 delims=\ " %%A IN ('REG QUERY HKLM\SYSTEM\MountedDevices /s ^|FIND "\DosDevices\" ^| FIND "4300640052006F006D"') DO set CDROM=!CDROM! %%A

SET CDROM

 

 

still not work after check each letter. But you help me with fsutil is enough for me, tks.

 

Return my question

SETLOCAL ENABLEDELAYED EXPANSIONSET /A Counter=1for %%b 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 (dir %%b:\ToolsforPE.ISO >nul 2>nul && (set isofile[!Counter!]=%%b:\ToolsforPE.ISO&&SET /A Counter+=1)IF NOT DEFINED isofile[1] echo ISO not foundbla ...

I try to add a line which set path=%%b to get letter where ISO found.

 

 

full code

@echo offSETLOCAL ENABLEDELAYEDEXPANSIONSET /A Counter=1for %%b 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 (dir %%b:\ToolsforPE.ISO >nul 2>nul && (set path=!path! %%b:set isofile[!Counter!]=%%b:\ToolsforPE.ISO&&SET /A Counter+=1)IF NOT DEFINED isofile[1] echo ISO not found)echo there is/are %counter% ISO found on %path%pause

but it return

there is/are 3 ISO found on C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\ c: d:

Don't know why

C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\

exist on output.

 

And just ask for sure, why we need set counter = 1 instead of 0. If set to 1, then if ISO was not found, it will output 1 ISO found.

tks

  • Upvote 1
Link to comment
Share on other sites

Well, no.

You need to study a minimal of the environment and of the batch syntax.

PATH is a "special" variable in Windows (and in DOS for this matters).

And you are not really "new" to batch, it's like two years that you are a member of MSFN and try writing small batches.

It seems like you take one snippet here (and one there) than modify them in a "random" or "semi-random" way and as soon as they don't work you ask for help here and as soon as you get an EXAMPLE, instead of studying it and trying to understand why it works (or why it doesn't work) you further modify it in a random or semi-random way, and this leads to another loop.

Try using "mypath" or "isopath" instead of "path" in that batch.

jaclaz

  • Upvote 2
Link to comment
Share on other sites

Well, no.

You need to study a minimal of the environment and of the batch syntax.

PATH is a "special" variable in Windows (and in DOS for this matters).

And you are not really "new" to batch, it's like two years that you are a member of MSFN and try writing small batches.

It seems like you take one snippet here (and one there) than modify them in a "random" or "semi-random" way and as soon as they don't work you ask for help here and as soon as you get an EXAMPLE, instead of studying it and trying to understand why it works (or why it doesn't work) you further modify it in a random or semi-random way, and this leads to another loop.

Try using "mypath" or "isopath" instead of "path" in that batch.

jaclaz

 

You're right. I'm not an coder and not usually work with code. I'm an economic students. But i love to know anything about "windows, booting" such as grub4dos, batch, ...

Before ask for help, i always write and test it myself. I read very many times from this link but still do not know all about .batch, even just for /f command.

After some examples which you give me, i learn a little from it. about !, about tokens, about delims  about [ ] ...

You help me in almost topic which I created and I'm sorry for about 2 year, from this topic to this topic, i'm still not know much about .bat and then you spend quite time and patient to help me.

About isopath if there are more than 1 ISO found, may i do not neet. Just simply output search result then ask user rename before rerun .bat

But still need you explain a thing, please

why we need set counter = 1 instead of 0. Output will return 1 even if ISO was not found.

 

 

Tks, Jaclaz.

  • Upvote 1
Link to comment
Share on other sites

Sorry for miss this.

 

After replace path with mypath as you say, it work fine.

Again, you teach me that: PATH is a "special" variable in Windows (and in DOS for this matters). Tks.

You help me in more ways than you realize.

  • Upvote 1
Link to comment
Share on other sites

I don't get the issue (if any) with setting counter=1

Here this:

 

SET /A Counter=1for %%b 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 (dir %%b:\ToolsforPE.ISO >nul 2>nul && (set isofile[!Counter!]=%%b:\ToolsforPE.ISO&&SET /A Counter+=1))set isofile[1]set counterIF NOT DEFINED isofile[1] echo ISO not found
results in isofile[1] NOT DEFINED if the iso has not been found.

 

What is the problem? :dubbio:

If you want to set initially Counter to 0 (or to 42) is good as well, as long as you make the check for isofile[0] or for isofile[42].

 

 

jaclaz

  • Upvote 2
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.


×
×
  • Create New...