Issue declaring an array and then using it's value

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Issue declaring an array and then using it's value

#1 Post by SIMMS7400 » 12 Mar 2021 04:28

Hi Folks -

I have an automation routine setup that performs a bunch of tasks. In all of my scripts, I first call an "environment" file to set a handful of variables for the given operation. In looking over my "environment" file, there is an opportunity to use an array to populate some variables to ensure it stays dynamic when porting over to another environment instead of having to edit each time.

The challenge is when setting up an array I need to use the command:
SETLOCAL ENABLEDELAYEDEXPANSION in the script but then when I call this "environment" script from my other scripts, obviously all variables set inside it are rendering nothing since they were local.

How do I get around this?

Here is the array in my "environment" script:

Code: Select all

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

FOR %%A IN (
	"HYPER-UTIL-PRD|PROD|net.tcp://HYPER-UTIL-aaa:5210/Oracle/Drm/ProcessManager|server1.client.com|server001.onetakeda.com"
	"HYPER-UTIL-TST|TEST|net.tcp://HYPER-UTIL-bbb:5210/Oracle/Drm/ProcessManager|server1.client.com|serverp002.onetakeda.com"
	"HYPER-UTIL-DEV|DEV|net.tcp://HYPER-UTIL-ccc:5210/Oracle/Drm/ProcessManager|server1.client.com|server003.onetakeda.com"
	) DO (
	
	FOR /F "tokens=1-5 delims=|" %%a IN (%%A) DO (
		SET "STR[%%a].HOST=%%a"
		SET "STR[%%a].ENV=%%b"
		SET "STR[%%a].DRM_URL=%%c"
		SET "STR[%%a].TM1_SERVER=%%d"
		SET "STR[%%a].TEMPO_SERVER=%%e"
	)
)

ECHO Host         = !STR[%COMPUTERNAME%].HOST!
ECHO Env          = !STR[%COMPUTERNAME%].ENV!
ECHO DRM URL      = !STR[%COMPUTERNAME%].DRM_URL!
ECHO TM1 Server   = !STR[%COMPUTERNAME%].TM1_SERVER!
ECHO Tempo Server = !STR[%COMPUTERNAME%].TEMPO_SERVER!

POWERSHELL -nop -c "& {sleep 5}"

::-- Set Environment --::
SET "_ENV=!STR[%COMPUTERNAME%].ENV!"

::--:::::::::::::::::::::::::::::::::--::
::-- SET PATH VARIABLES              --::
::--:::::::::::::::::::::::::::::::::--::

FOR %%A IN ("%~dp0..\..\..\..\Utilities") DO SET "UTILPATH=%%~fA\"
FOR %%A IN ("%~dp0..\..") DO SET "MAINPATH=%%~fA\"
SET "ARCHIVEPATH=%MAINPATH%Archives\"
SET "ERRORPATH=%MAINPATH%Errors\"
SET "FILEPATH=%MAINPATH%Files\"
And then I'm simply calling the above script as such from my other scripts:

Code: Select all

::-- Set Working Directory as Script Path --::
CD /D "%~dp0"

::-- Call Environment File --::
CALL "_env.cmd"
I need to still be able to access the variable inside my "environment" script. How would I go about doing this? Thanks!

SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Re: Issue declaring an array and then using it's value

#2 Post by SIMMS7400 » 12 Mar 2021 04:43

I think I got it. I need to set all of the variables with an array first and then implement and ENDLOCAL:

Code: Select all

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

FOR %%A IN (
"HYPER-UTIL-PRD|PROD|net.tcp://HYPER-UTIL-aaa:5210/Oracle/Drm/ProcessManager|server1.client.com|server001.onetakeda.com"
"HYPER-UTIL-TST|TEST|net.tcp://HYPER-UTIL-bbb:5210/Oracle/Drm/ProcessManager|server1.client.com|serverp002.onetakeda.com"
"HYPER-UTIL-DEV|DEV|net.tcp://HYPER-UTIL-ccc:5210/Oracle/Drm/ProcessManager|server1.client.com|server003.onetakeda.com"
) DO (

FOR /F "tokens=1-5 delims=|" %%a IN (%%A) DO (
SET "STR[%%a].HOST=%%a"
SET "STR[%%a].ENV=%%b"
SET "STR[%%a].DRM_URL=%%c"
SET "STR[%%a].TM1_SERVER=%%d"
SET "STR[%%a].TEMPO_SERVER=%%e"
)
)

ECHO Host = !STR[%COMPUTERNAME%].HOST!
ECHO Env = !STR[%COMPUTERNAME%].ENV!
ECHO DRM URL = !STR[%COMPUTERNAME%].DRM_URL!
ECHO TM1 Server = !STR[%COMPUTERNAME%].TM1_SERVER!
ECHO Tempo Server = !STR[%COMPUTERNAME%].TEMPO_SERVER!

POWERSHELL -nop -c "& {sleep 5}"

::-- Set Variables --::
SET "_ENV=!STR[%COMPUTERNAME%].ENV!"
SET "DRM_URL=!STR[%COMPUTERNAME%].DRM_URL!"
SET "TM1_SERVER=!STR[%COMPUTERNAME%].TM1_SERVER!"
SET "TEMPO_SERVER=!STR[%COMPUTERNAME%].TEMPO_SERVER!"

ENDLOCAL & (

SET "_ENV=%_ENV%"
SET "DRM_URL=%DRM_URL%"
SET "TM1_SERVER=%TM1_SERVER%"
SET "TEMPO_SERVER=%TEMPO_SERVER%"

)
Is this the correct way of going about it?

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Issue declaring an array and then using it's value

#3 Post by T3RRY » 12 Mar 2021 08:40

Setlocal and endlocal aren't necessary for this task.
When you use Goto :Eof in a batch script, an endlocal is assumed if Setlocal has been used.

The values in the array can be accessed by using a for /F loop over the Set command, meaning delayed expansion is never required eliminating the need to pass variable back over the Endlocal Barrier.

A small set of files to illustrate:

Caller.bat

Code: Select all

 @Echo off
 Call Environ.bat "input.txt"
 
input.txt

Code: Select all

Data 1|Data 2|Data 3|Data 4|Data 5
Environ.bat

Code: Select all

@Echo off
 For /F "Tokens=1-5 Delims=|" %%a in (%~1)Do (
  Set "Current.Host=%%a"
  Set "Host[%%a]=%%a"
  Set "Env[%%a]=%%b"
  Set "DRM Url[%%a]=%%c"
  Set "TM1 Server[%%a]=%%d"
  Set "Tempo Server[%%a]=%%e"
 )
 For %%G in (Host Env "DRM Url" "TM1 Server" "Tempo Server")Do (
  For /F "Tokens=1,2 Delims==" %%i in ('Set "%%~G[%Current.Host%"')Do Echo(%%i = %%j
 )

Compo
Posts: 600
Joined: 21 Mar 2014 08:50

Re: Issue declaring an array and then using it's value

#4 Post by Compo » 12 Mar 2021 11:30

…and to do it using much the same method as you had:

Code: Select all

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION

FOR /F "DELIMS==" %%G IN ('"(SET STR[%COMPUTERNAME%].) 2>NUL"') DO SET "%%G="

SET "_ALL=:5210/Oracle/Drm/ProcessManager|server1.client.com|"
FOR %%A IN (
	"HYPER-UTIL-PRD|PROD|net.tcp://HYPER-UTIL-aaa%_ALL%server001.onetakeda.com"
	"HYPER-UTIL-TST|TEST|net.tcp://HYPER-UTIL-bbb%_ALL%serverp002.onetakeda.com"
	"HYPER-UTIL-DEV|DEV|net.tcp://HYPER-UTIL-ccc%_ALL%server003.onetakeda.com"
) DO FOR /F "TOKENS=1-5 DELIMS=|" %%a IN (%%A
) DO IF /I "%%a" == "%COMPUTERNAME%" (
   SET "STR[%%a].HOST=%%a"
   SET "STR[%%a].ENV=%%b"
   SET "STR[%%a].DRM_URL=%%c"
   SET "STR[%%a].TM1_SERVER=%%d"
   SET "STR[%%a].TEMPO_SERVER=%%e"
)

IF DEFINED STR[%COMPUTERNAME%].ENV (
	SETLOCAL ENABLEDELAYEDEXPANSION
	ECHO Host         = !STR[%COMPUTERNAME%].HOST!
	ECHO Env          = !STR[%COMPUTERNAME%].ENV!
	ECHO DRM URL      = !STR[%COMPUTERNAME%].DRM_URL!
	ECHO TM1 Server   = !STR[%COMPUTERNAME%].TM1_SERVER!
	ECHO Tempo Server = !STR[%COMPUTERNAME%].TEMPO_SERVER!
	REM -- Set Environment --
	FOR %%G IN ("!STR[%COMPUTERNAME%].ENV!") DO ENDLOCAL & SET "_ENV=%%~G"
)

TIMEOUT /T 5 /NOBREAK 1>NUL

REM ------------------------
REM -- SET PATH VARIABLES --
REM ------------------------

FOR %%A IN ("%~dp0..\..\..\..\Utilities") DO SET "UTILPATH=%%~fA\"
FOR %%A IN ("%~dp0..\..") DO SET "MAINPATH=%%~fA\"
SET "ARCHIVEPATH=%MAINPATH%Archives\"
SET "ERRORPATH=%MAINPATH%Errors\"
SET "FILEPATH=%MAINPATH%Files\"

SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Re: Issue declaring an array and then using it's value

#5 Post by SIMMS7400 » 13 Mar 2021 03:54

Hi Compo -

Thanks so much, that certainly cuts down on the amount of lines necessary. My only question is how would I set all my variables so I can access them?

You have set _ENV here, but how do I set all of them from above?

Code: Select all

FOR %%G IN ("!STR[%COMPUTERNAME%].ENV!") DO ENDLOCAL & SET "_ENV=%%~G"
Or should I just access them in this manner when needed? i.e. !STR[%COMPUTERNAME%].DRM_URL! ?
Thanks!

Compo
Posts: 600
Joined: 21 Mar 2014 08:50

Re: Issue declaring an array and then using it's value

#6 Post by Compo » 13 Mar 2021 12:46

Which variables? my code defined every variable yours did! and all of them are available within the calling script upon return to it.

But assuming that you really do not need all of the variable names with [%COMPUTERNAME%] in them, you've created them unnecessarily.

For example:

Code: Select all

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION

FOR /F "DELIMS==" %%G IN ('"(SET _) 2>NUL"') DO SET "%%G="

SET "_ALL=:5210/Oracle/Drm/ProcessManager|server1.client.com|"
FOR %%A IN (
	"HYPER-UTIL-PRD|PROD|net.tcp://HYPER-UTIL-aaa%_ALL%server001.onetakeda.com"
	"HYPER-UTIL-TST|TEST|net.tcp://HYPER-UTIL-bbb%_ALL%serverp002.onetakeda.com"
	"HYPER-UTIL-DEV|DEV|net.tcp://HYPER-UTIL-ccc%_ALL%server003.onetakeda.com"
) DO FOR /F "TOKENS=1-5 DELIMS=|" %%a IN (%%A) DO IF /I "%%a" == "%COMPUTERNAME%" (
   SET "_HOST=%%a"
   SET "_ENV=%%b"
   SET "_DRM_URL=%%c"
   SET "_TM1_SERVER=%%d"
   SET "_TEMPO_SERVER=%%e"
)

…

SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Re: Issue declaring an array and then using it's value

#7 Post by SIMMS7400 » 14 Mar 2021 03:47

Hi Compo -

I replaced my section with yours:

Code: Select all

SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION

FOR /F "DELIMS==" %%G IN ('"(SET STR[%COMPUTERNAME%].) 2>NUL"') DO SET "%%G="

SET "_ALL=:5210/Oracle/Drm/ProcessManager|server1.client.com|"
FOR %%A IN (
	"HYPER-UTIL-PRD|PROD|net.tcp://HYPER-UTIL-aaa%_ALL%server001.onetakeda.com"
	"HYPER-UTIL-TST|TEST|net.tcp://HYPER-UTIL-bbb%_ALL%serverp002.onetakeda.com"
	"HYPER-UTIL-DEV|DEV|net.tcp://HYPER-UTIL-ccc%_ALL%server003.onetakeda.com"
) DO FOR /F "TOKENS=1-5 DELIMS=|" %%a IN (%%A
) DO IF /I "%%a" == "%COMPUTERNAME%" (
   SET "STR[%%a].HOST=%%a"
   SET "STR[%%a].ENV=%%b"
   SET "STR[%%a].DRM_URL=%%c"
   SET "STR[%%a].TM1_SERVER=%%d"
   SET "STR[%%a].TEMPO_SERVER=%%e"
)

IF DEFINED STR[%COMPUTERNAME%].ENV (
	SETLOCAL ENABLEDELAYEDEXPANSION
	ECHO Host         = !STR[%COMPUTERNAME%].HOST!
	ECHO Env          = !STR[%COMPUTERNAME%].ENV!
	ECHO DRM URL      = !STR[%COMPUTERNAME%].DRM_URL!
	ECHO TM1 Server   = !STR[%COMPUTERNAME%].TM1_SERVER!
	ECHO Tempo Server = !STR[%COMPUTERNAME%].TEMPO_SERVER!
	REM -- Set Environment --
	FOR %%G IN ("!STR[%COMPUTERNAME%].ENV!") DO ENDLOCAL & SET "_ENV=%%~G"
and then in my calling script, the only variable I am able to use in %_ENV%. How do I access the other ones? I'm confused then.

Compo
Posts: 600
Joined: 21 Mar 2014 08:50

Re: Issue declaring an array and then using it's value

#8 Post by Compo » 14 Mar 2021 06:10

The decision to create variable names which include a nested variable was yours, so in order to use those variables, you must do so by implementing another layer of variable expansion.

However, you do not need to create variables named using a nested variable, and I clearly showed you that in my later response. Please read it, comprehend it, and implement it, instead of seemingly ignoring it in favor of a previous response.

SIMMS7400
Posts: 546
Joined: 07 Jan 2016 07:47

Re: Issue declaring an array and then using it's value

#9 Post by SIMMS7400 » 16 Mar 2021 18:40

HI Compo -

I understand now. Yes, you are right I don't need to be as detailed as it was, unnecessary. I have used your suggestion and have been testing the last few days and everything is working as expected!! Thank you again!!

Post Reply