Batch Labels in a For Loop

November 20, 2010 at 19:22:47
Specs: Windows 7 Ultimate x64, Intel i5 @ 2.40 GHz / 8GB Ram
I have been using a scripting solution that was provided to me by nbrane and it's perfect for what I need. I use it ALL the time because it is awesome!!
It looks like this:

----------------------Begin Script----------------------

@Echo Off
for /f %%a in (\\Server1\apps$\Scripts\CompList\Computers-ON.txt) do (
echo processing to computer %%a


(Commands for each computer go here)


::--------End
)

----------------------End Script----------------------


However, now I have another twist. I need to add some decision logic to the script. I've found some code that will determine the version of the O/S, and now I need a: GoTo WinXP or GoTo Win7 However, when I add the label :WinXP or :Win7 ,the script will not run---Error: "The syntax of the command is incorrect."

This is the script that will NOT execute:


----------------------Begin Script----------------------

@Echo Off
for /f %%a in (\\Server1\apps$\Scripts\CompList\Computers-ON.txt) do (
echo processing to computer %%a

for /f "tokens=2*" %%i IN ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName ^| Find "ProductName"') DO set OSver=%%i %%j

echo %OSver% | find "Windows XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %OSver% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

:Win_XP
xcopy /O /Y \\Server1\apps$\Application\Shortcut\*.* \\%%a\c$"\Documents and Settings\All Users\Desktop\*.*"
GoTo NextComp

:Win_7
xcopy /O /Y \\Server1\apps$\Application\Shortcut\*.* \\%%a\c$\Users\Public\Desktop\*.*
GoTo NextComp

:NextComp

)

::--------End

----------------------End Script----------------------


If I remove all of the labels (:WinXP, :Win7, :NextComp) the script will run---of course I get other errors, but that's to be expected, since I don't have the labels in there.


Does anyone have any ideas or is more info needed?

Thanks in advance!!! Any help is much appreciated.

-------Mark


See More: Batch Labels in a For Loop

Report •


#1
November 20, 2010 at 21:11:07
Just out of curiosity what does:

echo %ALLUSERSPROFILE%

Output on win7?

It might help because you may not need to check the os ver.


Report •

#2
November 20, 2010 at 21:30:59
Silly me I just realized that you want the version of the remote pc.....

You are actually always testing the local machine with reg query,
I'm not sure about access rights but you may be able to:

... IN ('reg query "\\%%a\HKLM\SOFTWARE\ ...


As for :

if %ERRORLEVEL% == 0

Expansion in for loops is a bit different http://judago.webs.com/variablecatc...

The main problem:

if "%OSver%"=="Windows XP" (
       xcopy /O /Y \\Server1\apps$\Application\Shortcut\*.* \\%%a\c$"\Documents and Settings\All Users\Desktop\*.*"
)

if "%OSver%"=="Windows 7" (
....


Report •

#3
November 21, 2010 at 03:39:49
Here's the word from the man.

============================================

Name: IVO
Date: September 26, 2009 at 13:12:12 Pacific


It is not allowed to code GOTO statements that jump to labels defined inside
a For loop.; so the GOTO :SEARCHINLINE breaks the correct instruction flow of
the parent loop.

Inside For loops you must strictly conform to the rules of structured
progranning coding CALL to local subroutines (CALL :LABEL parameters) to
workaround this issue.


=====================================
Life is too important to be taken seriously.

M2


Report •

Related Solutions

#4
November 21, 2010 at 07:07:52
I would take the IF statements out of the FOR loop, and instead create a variable that you can use inside the loop:

if "%remoteMachineVer%" == "..." (
set desktop=...
) else if "%remoteMachineVer%" == "..." (
set desktop=...
) else (
echo Error etc.
exit /b 1
)

... and then just use "%desktop%\filename" inside your loop.


Report •

#5
November 22, 2010 at 15:32:44
First of all, a great GREAT BIG THANK YOU to everyone who responded to my question—I appreciate it. By using parts from each of your responses, here is what I’ve come up with:

::----------------------------------------------------------------
::--------------------------------Begin Script--------------------------------
::----------------------------------------------------------------

@Echo Off

::----------------------------------------------------------------------------------------------
::------------VB Script to create list of computers that are ON------------
::----------------------------------------------------------------------------------------------

CScript \\Server1\Apps$\Scripts\Ping\CheckComps-ON.vbs


::-----------------Give the VBS script time to complete--------------------

Sleep 60

::----------------------------------------------------------------
::---------------------------------Main Script---------------------------------
::--------Iteriates through the list of Comps that are ON--------
::----------------------------------------------------------------

for /f %%a in (\\Server1\apps$\Scripts\CompList\Comps-ON.txt) do (
Echo Processing Computer %%a

xcopy /O /E /Y \\Server1\apps$\NewApp\C_\*.* \\%%a\c$\*.* > nul
xcopy /O /Y \\Server1\apps$\NewApp\C_Windows\*.* \\%%a\c$\Windows\*.* > nul
xcopy /O /Y \\Server1\apps$\NewApp\C_Windows_System32\*.* \\%%a\c$\Windows\System32\*.* > nul
psexec \\%%a -u domain\admin -p password -accepteula -n 30 -h Reg Import \\Server1\apps$\NewApp\Registry\NewApp.reg > nul

Set CurComp=%%a

CALL :ChkOSver

)

::--------End Main Script--------

Exit /B 0

::------------------------------------------------
::----------SUB to Check O/S Version---------
::------------------------------------------------

:ChkOSver
for /f "tokens=3*" %%i IN ('reg query "\\%CurComp%\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName ^| Find "ProductName"') DO set CurCompOS=%%i %%j

echo %CurCompOS% | find "Windows XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %CurCompOS% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

:Win_XP
xcopy /O /Y \\Server1\apps$\NewApp\Shortcut\*.* \\%CurComp%\c$"\Documents and Settings\All Users\Desktop\*.*" > nul
GoTo NextComp

:Win_7
xcopy /O /Y \\Server1\apps$\NewApp\Shortcut\*.* \\%CurComp%\c$\Users\Public\Desktop\*.* > nul
GoTo NextComp

:NextComp
Set CurComp =

::------------------------------------------------
::-------------Return to Main Script-------------
::------------------------------------------------

If anyone sees anything in this script that can be done more efficiently, please let me know—I’m wide open for suggestions.

@klint - I'm curious as to how you would implement your bit of code into what I have. Maybe that would be more efficient, but I didn't quite understand. Sorry.

Once again, a huge Thank You to everyone for your help!!!!


----------Mark


Report •

#6
November 23, 2010 at 05:05:22
It's ok, I misunderstood the original problem and thought the OS version checking could be taken out of the loop and done just once at the start of the batch file. But it can't since it's the version of each computer you need to check.

One other thing I noticed: why do you wait 60 seconds for the VBScript to complete? I thought the batch file waits until the CScript.exe process terminates, so it should already be complete by the time you get to the next line of the batch file.


Report •

#7
November 23, 2010 at 11:22:52
First of all, let me say that I don't consider myself a "coder". My motto is that somewhere in the world, someone has already had the same issue or idea that I'm having. So I search around for pieces of code that will do something close to what I need, I put it all together, and massage it to get it to work for me. I like the challenge of learning code--Batch Files, VB Scripts, even PowerShell scripts. I have a (licensed) installation of Visual Studio 2010 Ultimate for dabbling in Websites and databases, and I've taken college courses in Visual Basic.

So, klint, getting back to your question (enough about me), what I've noticed is that when I run the script listed above, while the VB script is running I don't have any visual feedback that something is happening, and as such I honestly don't know when it's ("CheckComps-ON.vbs") completed--or even if it completed!!

So just to be safe, I added the "Sleep 60" to make sure and give the VB script time complete, and properly close, the newly created text file of computers that are ON ("Comps-ON.txt"). I figured that way, the batch file would fire up and run without any crying about not being able to "open a file for reading" and such.

I would be glad to let you (klint)(or anyone for that matter) take a look at the VB script to see if it's running efficiently. Also, maybe you could show me a way to add some type of visual feedback, or at least ensure that the VB script ("CheckComps-ON.vbs") has completed creating--and properly closed--the "Comps-ON.txt" _before_ the batch file continues processing.

Is there a way to "attach" a file to these post? The VB script is rather long. I don't mind posting it here, but it may get "scrambled".

Anyone interested?

Once again, Thanks!! to everyone for the replies. It's refreshing to know that there are people like yourselves who don't mind sharing knowledge or helping to solve a problem.

Thanks a bunch guys.


----------Mark


Report •

#8
November 24, 2010 at 12:31:00
Ok guys, I am fairly certain that there is a problem with this script. It _appears_ that the "CheckOSver" sub routine isn't working. After some testing, the script failing here:


echo %CurCompOS% | find "Windows XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %CurCompOS% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

The %CurCompOS% variable is being set correctly, but the script is not honoring the "GoTo" statements in the second line. It always goes to the Win_XP label.

So, could something be incorrect in this line:
"for /f "tokens=3*" %%i IN ('reg......"

Maybe something in this portion of the sub:
"echo %CurCompOS% |......"
isn't functioning properly.

Could it be that the
"... | find "Windows......."
isn't finding the correct information?

Maybe the line:
"if %ERRORLEVEL% == 0......"
is not being processed correctly?

I've seen references to something about "Delayed Expansion" for variables, so am I missing something to do with that?

@Judago, I've read the content of the of the website that you listed above, but I'm still a bit confused.

Any help is MUCH appreciated.

Thanks,


----------Mark


Report •

#9
November 24, 2010 at 14:28:21
You can avoid this whole mess:

echo %CurCompOS% | find "Windows XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %CurCompOS% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

with:

goto :%CurCompOS%


=====================================
Life is too important to be taken seriously.

M2


Report •

#10
November 24, 2010 at 17:23:39
Thank you for the quick response.

However, at this point in the script, the value of %CurCompOS% is either:

"Microsoft Windows XP"

or

"Windows 7 Professional"


What method would you suggest to change the value of %CurCompOS% to something more manageable? I suppose that I would need something without spaces-- "Win_XP" or "Win_7" so that I can use them as GoTo labels.

Any ideas anyone?

Thanks a bunch,


----------Mark


Report •

#11
November 24, 2010 at 17:32:20
You can change the label to ":MicrosoftWindowsXP" and ":Windows7Professional" then do "GOTO :%CurCompOS: =%"

Can I put a question here?


Report •

#12
November 25, 2010 at 02:28:25
I don't have a ProductName registry value on any of my PCs. Are you sure it exists?

As for the VB script, no need to send it in, just add this line just before it exits:

WScript.Echo "Script finished."


Report •

#13
November 30, 2010 at 19:14:22
Ok everyone, sorry for the delayed response.

So, here is the script as it stands for the moment (I’ve removed some of the unnecessary code):

::--------Begin Main Script--------

@Echo Off

for /f %%a in (\\Server1\apps$\Scripts\CompList\Comp_List-Test.txt) do (

Echo Processing Computer %%a

:: Some Code goes here
::
::
:: Yada Yada Yada…..

Set CurComp=%%a

CALL :ChkOSver

)

::--------End Main Script--------

Exit /B 0

::-------------------------------------------
::----------SUB to Check O/S Version---------
::-------------------------------------------

:ChkOSver
for /f "tokens=3*" %%i IN ('reg query "\\%CurComp%\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName ^| Find "ProductName"') DO set CurCompOS=%%i %%j

echo %CurCompOS% | find "Windows XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %CurCompOS% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

:Win_7
Echo The Current GoTo Setting is Win_7
Echo.
Echo The Current OS is ----- %CurCompOS%
Echo.
Pause
GoTo NextComp

:Win_XP
Echo The Current GoTo Setting is Win_XP
Echo.
Echo The Current OS is ----- %CurCompOS%
Echo.
Pause
GoTo NextComp

:NextComp
Set CurComp =
Set CurCompOS =

::-----------------------------------------------
::-------------Return to Main Script-------------
::-----------------------------------------------

PART 1_______
Since I can’t seem to grasp the concept of “Tokens”, then:
QUESTION: Is the “For /f "tokens=3*" %%i” portion of the subroutine correct in this instance, for this particular script, and for what I’m attempting to accomplish?
QUESTION: Is that entire line correct?

PART 2________
If I run the script on a Windows XP machine or a Windows 7 machine, I get the same response: The first GoTo label (after :ChkOSver) is the label that is used. It doesn’t matter if the :Win_XP label is first or the :Win_7 label is first, or if I run the script on a Windows 7 or a Windows XP machine, with any combination thereof.

So, after much testing, I think the issue is here:

echo %CurCompOS% | find "Windows XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %CurCompOS% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

@Mechanix2Go: I tried what you suggested (goto :%CurCompOS%)---No Joy.

@ Matt123: Then I tried your suggestion: (change the label to ":MicrosoftWindowsXP" and ":Windows7Professional" then do "GOTO :%CurCompOS: =%")----No Joy. I guess I don’t understand the purpose of the “: =%” portion of the GoTo label.

@klint: “Yes, Virginia, there is a Santa Claus” (Sorry for the cheap movie quote…..).

@klint, the 2nd part of your post worked like a champ!! (WScript.Echo “Script Finished”) Thanks a bunch.

PART 3________

I’m stumped—any additional ideas anyone?

Thanks to everyone for hanging in there with me on this. I really appreciate it.

AC/DC........"Who made who......".......


----------Mark


Report •

#14
November 30, 2010 at 19:31:04
UPDATE:
I just found a post: "Batch Files: Tokens and Delimiters (FOR Loops)" in the Programming forum. I think I understand "Tokens" now.


----------Mark


Report •

#15
November 30, 2010 at 19:55:53
UPDATE: SOLVED!!!!

This works like a champ!!!!

::-------------------------------------------
::----------SUB to Check O/S Version---------
::-------------------------------------------

:ChkOSver
for /f "Tokens=* Delims= " %%i IN ('reg query "\\%CurComp%\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName ^| Find "ProductName"') DO set CurCompOS=%%i %%j

echo %CurCompOS% | find "XP" > nul
if %ERRORLEVEL% == 0 GoTo Win_XP

echo %CurCompOS% | find "7" > nul
if %ERRORLEVEL% == 0 GoTo Win_7

:Win_XP
xcopy /O /Y \\Server1\apps$\NewApp\Shortcut\*.* \\%CurComp%\c$"\Documents and Settings\All Users\Desktop\*.*" > nul
GoTo NextComp

:Win_7
xcopy /O /Y \\Server1\apps$\NewApp\Shortcut\*.* \\%CurComp%\c$\Users\Public\Desktop\*.* > nul
GoTo NextComp

:NextComp
Set CurComp =
Set CurCompOS =


::-----------------------------------------------
::-------------Return to Main Script-------------
::-----------------------------------------------


The problem was here:
ORIGINAL: for /f "Tokens=3*"
REVISED: for /f "Tokens=* Delims= "

Thanks to everyone for their patience and suggestions.

Thanks guys!!!


----------Mark


Report •


Ask Question