How to persistently add directories to PATH when using SETLOCAL? [duplicate] - windows

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Make an environment variable survive ENDLOCAL
How to keep the value of a variable outside a Windows batch script which uses “delayed expansion local” mode?
I have a batch file that goes something like this:
REM I need to use SETLOCAL so as not to pollute the environment
REM with any variables used to implement the logic in this script
SETLOCAL
SET I_DONT_WANT_THIS_VARIABLE_TO_LEAK_OUTSIDE=c:\
REM BUT, there is this one change to the environment I want to make sticky:
PATH %PATH%;%I_DONT_WANT_THIS_VARIABLE_TO_LEAK_OUTSIDE%
The script uses SETLOCAL to isolate the environment from whatever the batch file wants to do, but this causes a problem: at the end I do want to modify the caller's environment in some very specific manner, but SETLOCAL prevents this (the change is undone as soon as the batch file exits). I also cannot call ENDLOCAL before setting the path because that restores the environment to its original state, wiping out the value of the variable so I cannot append its value to the path.
Is there a way to set the path while ignoring the SETLOCAL in effect? Alternatively, is there any trick to explicitly preserve the value of a variable from being wiped out when calling ENDLOCAL?
I am aware that it's possible to use a temp file as a vessel that can bypass the ENDLOCAL barrier, but a more elegant solution would be welcome.

Add this to the end of your script (or just before you return):
endlocal & #set path=%path%
The reason that this works is that the cmd parser performs environment variable expansion to the entire line before executing any of it. So by the time endlocal executes, the line that cmd is processing looks like:
endlocal & #set path=c:\whatever\the;c:\new\path;c:\is
Then endlocal throws away all the local changes, but the ones made to the path have been temporarily preserved in the set command that's about to be executed.

Related

Returning string from external function batch

I have two batch files. One is the main (caller) file and one is a function.
The function takes one parameter, does some stuff and then i wanna return the string to the caller (main.bat). %ERRORLEVEL% is not an option, as it can only return integers.
main.bat:
call function.bat hello
function.bat:
REM some code.......
[HERE THE CODE TO RETURN A STRING TO CALLER FILE]
Seems like a basic operation, so there must be a way. Also, i prefer not making files with the output and reading it in the main.bat, because i want to make it work as a easy-to-use function.
The two batch files are executed both by same Windows command processor process and share therefore all environment variables.
Main.bat:
#echo off
set "MyVariable="
call Function.bat hello
echo MyVariable=%MyVariable%
Function.bat:
#echo off
rem Some code ...
set "MyVariable=%~1"
It could be that Function.bat uses for some reason command SETLOCAL. In this case all environment variables defined as well as all modifications made on environment variables after the command SETLOCAL are lost after corresponding ENDLOCAL. This command is implicitly called by Windows command processor on exiting execution of a batch file for each SETLOCAL not yet completed with explicit execution of corresponding ENDLOCAL. Read this answer for details about the commands SETLOCAL and ENDLOCAL.
It is necessary to explicitly set an environment variable on same command line as the command ENDLOCAL with using immediate environment variable expansion to pass value of an environment variable from current environment variables list to previous environment variables list.
Function.bat:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Some code ...
set "MyVariable=%~1"
endlocal & set "MyVariable=%MyVariable%"
The last command line is preprocessed first by Windows command interpreter to
endlocal & set "MyVariable=hello"
So the command line after preprocessing does not contain anymore any variable reference. The command ENDLOCAL restores previous environment which results in deletion of environment variable MyVariable. But the second command SET specified on same command line sets this variable once again with the value hello in restored environment.
See also Single line with multiple commands using Windows batch file.

Windows prompt content variable as variable name

It is possible in windows command line refer to a content variable like a pointer?
Example:
SET envTEST=FOO
SET envPROD=BAR
SET CURR=envTEST
SET data=%%CURR%%
I want to data contains FOO but it contains %envTEST%
Thanks
You need multiple rounds of expansion. See How does the Windows Command Interpreter (CMD.EXE) parse scripts? for an explanation as to why the following work:
From the command line:
call set "data=%%CURR%%"
Or if delayed expansion has been enabled by cmd /v:on, then:
set "data=!%CURR%!"
From within a batch script:
call set "data=%%%CURR%%%
or
setlocal enableDelayedExpansion
...
set "data=!%CUR%!
If CURR is set and expanded within the same code block (typically done within IF or FOR loop), then:
setlocal enableDelayedExpansion
...
(
set "CURR=envTEST"
for %%V in (!CURR!) do set "data=!%%V!"
)
The CALL technique is quite slow, so I try to avoid it. It is not an issue for a single use, but it can become a major problem (slow performance) if used within a tight loop.

Windows Batch setting PATH through loop

I'm trying to create a drive with a suite of programs that can be implemented through the command prompt.
My issue is setting the PATH environment variable to include paths to the program suite. Since there are a couple directories for these suites (and I'm constantly adding more), I am trying to get it so I can have a .ini file be parsed through a simple Batch script and returned. From this I want to take the path parsed from the .ini file and append it to my current PATH variable.
This is the current script I'm trying to get fixed.
FOR /F "delims=" %%i IN ('call %cd:~0,3%\initTermPort\parse.ini.bat %cd:~0,3%\initTermPort\config.ini Alternate _path') DO (
SET PATH="%PATH%;%cd:~0,3%%%i"
)
The call to parse.ini.bat is getting the next path in config.ini on every run.
For example:
If I substitute SET PATH="%PATH%;%cd:~0,3%%%i" with ECHO %%i I get the following output:
E:\> (ECHO ~\bin)
~\bin
E:\>(ECHO ~\library\bin)
~\library\bin
But for some reason SET PATH="%PATH%;%cd:~0,3%%%i" is not setting the PATH at all.
Any help is appreciated.
The problem is that when the for code block (the code enclosed in parenthesis) was parsed, all the read operations to variables were replaced with the value in the variable before starting to execute, and in each iteration what is used is this initial value, and not the value inside the variable during the execution.
If you change a variable inside a block of code and need to access the changed value inside the same block of code, you need to enable delayed expansion and change the syntax to access the variables to use !varName! instead of %varName%. This indicates to the parser that this read operation must be delayed.
setlocal enableextensions enabledelayedexpansion
....
FOR /F "delims=" %%i IN (
'call %cd:~0,3%\initTermPort\parse.ini.bat %cd:~0,3%\initTermPort\config.ini Alternate _path'
) DO (
SET "PATH=!PATH!;%cd:~0,3%%%i"
)

Concatenate file paths to an environment variable in batch script

I have made a bat script that should copy the list of folders to a variable but I don't get anything in the variable. In other words, when I echo the variable after my for loop I get the expected output, but in the shell outside after executing the script, I don't see anything set in my variable. How can I get all the variables to copy correctly?
I am using Windows 7.
Batch FIle (script.bat):
#echo off
setlocal enabledelayedexpansion enableextensions
for /r /D %%x in (*) do (
SET PATH_VALUE=%%x;!PATH_VALUE!
)
echo %PATH_VALUE%
Output of windows cmd utility
C:\test> script.bat
C:\test\1;C:\test\2
C:\test> echo %PATH_VALUE%
%PATH_VALUE%
How do I get the %PATH_VALUE% as an environment variable? I found a similar question here but it doesn't quite answer my case.
That is because of your SETLOCAL command that you use to enable delayed expansion. Yes it provides the delayed expansion you need, but it also localizes environment changes. As soon as your batch script ends, there is an implicit ENDLOCAL, and the old environment is restored.
You can pass the value across the ENDLOCAL barrier by adding the following to the end of your script:
endlocal&set "PATH_VALUE=%PATH_VALUE%"
or you could write it like:
(
endlocal
set "PATH_VALUE=%PATH_VALUE%"
)
Both of the above work because the blocks of code are expanded and parsed prior to the ENDLOCAL executing, but the SET statement with the expanded value is executed after the ENDLOCAL.

using set variable in copy command

How can I copy a file inside a bat file using a set variable.
[run.bat]
set MY_WORKSPACE=workspace1.0.1
copy /Y /V D:\%MY_WORKSPACE%\webapp\target\app-generic.war C:\Opt\jboss-4.2.3.GA\server\default\deploy\
In above example, %MY_WORKSPACE% is invalid, however I can see the value by using 'echo'
Is that the whole batch file you're showing us?
I have a vague feeling you're doing the set and copy inside an if or similar statement with a block, e.g.
if foo==bar (
set MY_WORKSPACE=workspace1.0.1
copy ...
)
In this case you need delayed expansion for the variable change to take effect because the block in parentheses is parsed as a single command and all variables are substituted at parse time, not when runnin a command. Therefore %MY_WORKSPACE% will be empty once the block runs.
You can solve this by using
setlocal enabledelayedexpansion
at the top of your batch file and using !MY_WORKSPACE! instead of %MY_WORKSPACE% which will expand the variable just prior to running the command, not while parsing.
Try this way:
set MY_WORKSPACE="workspace1.0.1"

Resources