0

I'm trying to use CMDER for a development environment that I've setup.

Basically I've created a .bat file that calls:

@ECHO OFF 
start Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\Cmder.exe

Then I've placed the file startdev.bat in: %CMDER_HOME%\config\profile.d

So everything seems to work just fine, but when the startdev.bat finishes, issuing an:

echo %PATH%

returns:

Z:\_DEV\OS_WINDOWS\1_COMPILER\JDK\ORACLE\1.8.0_181\bin;Z:\_DEV\OS_CYGWIN\bin;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CLutils;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\PUTTY;Z:\_DEV\OS_WINDOWS\6_VERSION_CONTROL\PortableGit\bin;C:\WINDOWS;C:\WINDOWS\SysWOW64;C:\WINDOWS\System32

...any idea what's happening?

I would either expect CMDER to override PATH with the value from its own settings, or use my full path, which before the startdev.bat ends shows the value of:

PATH=Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5\ConEmu;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5\ConEmu\Scripts;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\GRADLE\5.4\bin;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\MAVEN\3.5.4\bin;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\ANT\1.10.5\bin;Z:\_DEV\OS_WINDOWS\3_BUILD_TOOLS\NODE\LTS\10.15.3;Z:\_DEV\OS_WINDOWS\3_BUILD_TOOLS\NODE\LTS\10.15.3\node_modules;Z:\_DEV\OS_WINDOWS\1_COMPILER\GO\1.12.4\bin;Z:\_DEV\OS_WINDOWS\1_COMPILER\PYTHON\32bit\2.7.13;Z:\_DEV\OS_WINDOWS\1_COMPILER\PYTHON\32bit\2.7.13\scripts;Z:\_DEV\OS_WINDOWS\1_COMPILER\ANDROID\android-sdk-windows\platform-tools;Z:\_DEV\OS_WINDOWS\1_COMPILER\JDK\ORACLE\1.8.0_181\bin;Z:\_DEV\OS_CYGWIN\bin;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CLutils;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\PUTTY;Z:\_DEV\OS_WINDOWS\6_VERSION_CONTROL\PortableGit\bin;C:\WINDOWS;C:\WINDOWS\SysWOW64;C:\WINDOWS\System32

..but the fact that it only seems to be keeping the value as defined about halfway through the batch job is strange.

Any ideas?

Community
  • 1
  • 1
ZacWolf
  • 752
  • 5
  • 18
  • Perhaps it's about system and user environment. I don't understand why cmder needs magic with profile.d, all environment you may set up natively in ConEmu settings. – Maximus Apr 18 '19 at 22:42
  • As @Maximus said, the value of `%PATH%` is the joined contents from both the user and machine environments. You appear to have overwritten only the content of one of them. – Compo Apr 18 '19 at 23:37

2 Answers2

1

First I recommend opening a command prompt window and run setlocal /? and endlocal /? to get displayed the help/documentation for those two commands. Very important to know is that every setlocal without a corresponding endlocal results in an implicit execution of endlocal by cmd.exe before exiting processing of a batch file or a subroutine called with command CALL.

Next I suggest reading this answer for even more details about the commands SETLOCAL and ENDLOCAL and what happens on using them.

I suggest like michael_heath to change this code block:

setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
    set CLASSPATH=!CLASSPATH!;%%a
)
set CLASSPATH=!CLASSPATH!

Better would be:

setLocal EnableExtensions EnableDelayedExpansion
set CLASSPATH=.
for /R "%JRE_HOME%\lib" %%a in (*.jar) do set "CLASSPATH=!CLASSPATH!;%%a"
endlocal & set "CLASSPATH=%CLASSPATH%"

Now the local environment is ended with passing the environment variable CLASSPATH from local environment, on which it was defined, to the restored previous environment because of cmd.exe expands %CLASSPATH% to current value of the environment variable CLASSPATH in current local environment before executing the command endlocal which restores the previous environment.

Wrong in your batch file is also set WINDIR=%SystemRoot%;%SystemRoot% which should be set "WINDIR=%SystemRoot%".

I recommend further reading Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains why the syntax set "variable=string value" is recommended nowadays. Many of the environment variable definitions use directly or indirectly %UserProfile% which means depending on whatever the user currently running the batch file has entered as user name on creation of the user account. I have seen users entering their name containing a space and non ASCII characters. And I have seen users creating an account with a user name containing character & like Company GmbH & Co. An ampersand outside a double quoted argument string is interpreted as AND operator and cmd.exe tries to execute after set also the remaining string after & as command line on using something like set USERHOME=%DEVHOME%\%USERNAME% instead of set "USERHOME=%DEVHOME%\%USERNAME%". Well, startdev.bat redefines nearly all predefined Windows Environment Variables including USERNAME and USERPROFILE and so is written safe for most environment variable definitions.

This code block is also not optimal:

FOR /F "usebackq" %%i IN (`hostname`) DO SET HOSTNAME=%%i
echo Running on hostname: %HOSTNAME%

The host name respectively computer name could contain also a space or characters critical for command line or start with a semicolon for some unknown reason. So better would be:

FOR /F delims^=^ eol^= %%i IN ('hostname') DO SET "HOSTNAME=%%i"
setlocal EnableDelayedExpansion & echo Running on host name: !HOSTNAME!& endlocal

Whereby there is the environment variable COMPUTERNAME predefined by Windows making it possible to use just following command line:

setlocal EnableDelayedExpansion & echo Running on host name: !ComputerName!& endlocal

An ECHO command line containing an immediately expanded environment variable reference on which it is unknown if its value contains &|<> is always a problem because of the environment variable reference is expanded before further processing of the command line by cmd.exe as described at How does the Windows Command Interpreter (CMD.EXE) parse scripts?

I suggest also reading DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ and avoid the usage of echo. in the batch file to output an empty line.

Mofi
  • 46,139
  • 17
  • 80
  • 143
0

"halfway through the batch job" as you have a setLocal EnableDelayedExpansion which sets any further changes to the variable PATH or other set variables as local. The endLocal not specified is implied at the end of the script.

To resolve this, use endLocal and set CLASSPATH=%CLASSPATH% on the same parsed line to set CLASSPATH as global.

Change this part:

    setLocal EnableDelayedExpansion
    set CLASSPATH=.
    for /R %JRE_HOME%\lib %%a in (*.jar) do (
        set CLASSPATH=!CLASSPATH!;%%a
    )
    set CLASSPATH=!CLASSPATH!

to this:

    setLocal EnableDelayedExpansion
    set CLASSPATH=.
    for /R %JRE_HOME%\lib %%a in (*.jar) do (
        set CLASSPATH=!CLASSPATH!;%%a
    )
    endLocal & set CLASSPATH=%CLASSPATH%

After that changed part, the script will set variables as global again.

michael_heath
  • 5,262
  • 2
  • 12
  • 22
  • Thanks so much for this! Excellent information, but since @Mofi goes into a bit more detail I awarded him the answer. But thanks for the answer!!! – ZacWolf Apr 19 '19 at 15:30