Limits on Windows environment variable nesting? - windows

So, is there a limit to how deeply environment variables can be nested in Windows? I do a lot of development work and I'm trying to set up my development environment vars, and a lot of them nest off each other, ie.
GLEW=%THIRD_PARTY_ROOT%\GLEW
GLEW_1_5_5=%GLEW%\glew-1.5.5
GLEW_BIN_PATH=%GLEW_ROOT%\bin
GLEW_INCLUDE_PATH=%GLEW_ROOT%\include
GLEW_LIB_PATH=%GLEW_ROOT%\lib
GLEW_ROOT=%GLEW_1_5_5%
OSG=%THIRD_PARTY_ROOT%\OpenSceneGraph
OSG_2_8_3=%OSG%\OpenSceneGraph-2.8.3
OSG_BIN_PATH=%OSG_ROOT%\bin
OSG_INCLUDE_PATH=%OSG_ROOT%\include
OSG_LIB_PATH=%OSG_ROOT%\lib
OSG_ROOT=%OSG_2_8_3%
THIRD_PARTY_ROOT=C:\dev\third-party
But I was having a heck of a time getting them to actually expand properly. For a while when I looked at the output of set, I was just getting what looked like they were being expanded in order and so any ones that depended on foo_ROOT weren't being expanded properly. I tried enabling delayed expansion and that didn't help, but restarting seemed to... so maybe delayed expansion required a restart..
Either way, I have GLEW_BIN_PATH and OSG_BIN_PATH in my PATH variable and they refuse to expand. This is really frustrating because the dll's are residing there and of course I can get evvvverything else to expand... any thoughts?
Edit: I have them in the PATH variable as:
[everything else....];%GLEW_BIN_PATH%;%OSG_BIN_PATH%
So I'm not seeing an obvious cause to keep them from expanding out..

It looks like there is a lexicographic dependency on the variables definition.
Windows expands and populates the Enviroment Variables on lexicographic order (:-O)
You can only use on your variable, variables that are "lexicographically" lower than your variable.
Example:
Following Definition:
VAR_01=1
VAR_02=%VAR_01%-2
VAR_03=%VAR_02%-3
Produces
VAR_01 is 1
VAR_02 is 1-2
VAR_03 is 1-2-3
But
VAR_01=1
VAR_02=%VAR_03%-2
VAR_03=%VAR_01%-3
Produces
VAR_01 is 1
VAR_02 is -2
VAR_03 is 1-3
Due VAR_03 is not defined when VAR_02 is expanded.

Yeah, this is driving me crazy. Full repro by:
System Properties, Environment Varialbles, set up like so:
one = c:
two = %ONE%\two
three = %TWO%\three
Then click OK, and run cmd. Here's what I see:
C:\>set one
one=C:
C:\>set two
two=C:\two
C:\>set three
three=%TWO%\three
This link explains for Vista, but does not mention that it happens on Win7.
http://support.microsoft.com/kb/911089
...Jonas

I've had success with escaping the percent sign:
GLEW=%%THIRD_PARTY_ROOT%%\GLEW
THIRD_PARTY_ROOT=C:\dev\third-party
C:\>set GLEW
GLEW=C:\dev\third-party\GLEW
When viewing the variable from the Windows Environment Variable window, it will display as
GLEW | %THIRD_PARTY_ROOT%\GLEW
Note: The double percent signs will only work inside a script. If using on the command line, use the caret escape character (e.g. GLEW=^%THIRD_PARTY_ROOT^%\GLEW).

Have you saved all of the needed variables in the System Variables as well? Because in order to expand the values, the system will have to have a "permanent" memory of all the needed variables.
If you do all these together in a row on the command line, just saying X=something and Y=%X%;else, then when you set the path to PATH=%PATH%;%Y%, the shell expands the values of all the variables before it saves the new value of PATH; but as soon as you close the Command Prompt window, the system has forgotten %X% and %Y% entirely.
However, if you use the System Properties Control Panel to set the PATH to include the unexpanded variables, than all those variables are going to have to exist as system variables when you reboot, or they'll fail to expand.
To ensure that you are saving all the variables in the system so that they are still there after the reboot, either use the System Properties Control Panel or the SETX.EXE command. If you are going to use them in the system PATH (not just your user account's path), then you'll want to use SETX /M X=blah or the bottom part of the System Properties | Environment Variables tab, labeled "System variables".

I have been experiencing this in Windows 10, build 1903.
For me, the solution was to remove the PATH variable from 'user' (the upper half of the system properties dialog) and keep only the path in 'system'. Restart the cmd.exe shell or use refreshenv to reload the properties, and expansion should work again.
This looks like a bug in Windows for how it resolves user vs system properties, or possibly the processing order. For me it was not replacing values in the user PATH with values from the 'system' set of env vars. It might work better if all the variables are in user, but I've not tested this hypothesis.

Related

Environment variables not working properly

I'm trying to run an application that reads an environment variable that contains a JSON with about 22k characters. The project setup tells me to use $(cat ./path/to/file) to correctly configure it, but as I'm using windows, this commands do not work.
I've tried copying the contents of the file to the variable using the GUI Environment Variable, but its input truncates the value to a certain limit which is not even on half of the file.
After this I tried setting the variable using the Powershell with the command:
$env:myvar = iex '$(type path/to/file)'
and then saving the result with:
[System.Environment]::SetEnvironmentVariable('MYVAR', $env:MYVAR, [System.EnvironmentVariableTarget]::Machine)
After these commands, Powershell is able to print the result correctly but CMD still prints only part of the value when I echo it.
This is very odd because the regedit shows the correct value as suggested here.
The application still can't process the value because it is not complete.
Is there any fix for this?
Note: This answer applies to Windows.
tl;dr
While you can store up to 32,766 characters in a single environment variable, the standard retrieval mechanisms in cmd.exe and PowerShell / .NET (as of v7.1 / 5.0) support only up to 4,095.
A workaround in PowerShell is possible, but ultimately it comes down to whether the target executable that is meant to read an environment-variable value supports reading values up to the technical maximum length.
The technical limit for the number of characters in a single environment variable is 32,766 (32KB = 32768, minus 2).
Starting with Windows Server 2008 / Windows Vista, there is no longer a limit on the overall size of the environment block - see the docs.
However, depending on how the environment-variable is retrieved, the limit may be lower:
Both cmd.exe and PowerShell, as of v7.1 / .NET 5.0, support retrieving at most 4,095 characters.
However, in PowerShell you can retrieve longer values, assuming the variable of interest is defined persistently in the registry, and assuming that you know whether it is defined at the machine or user level; e.g., for a MYVAR environment variable:
At the machine level:
Get-ItemPropertyValue 'registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' MYVAR
At the user level:
Get-ItemPropertyValue registry::HKEY_CURRENT_USER\Environment MYVAR
try the type command. It is the windows equivalent of the unix cat command. This means storing the json inside of a seperate file and using the command "type <path_to_file>".

Is there a way to hide the current directory while typing commands in Cygwin

It is kinda annoying to have the path show each time i write a command. Is there a way to make it so that only the $ sign shows when i execute a command by pressing enter?
Sure, set your PS1 environment variable. See http://www.cyberciti.biz/tips/howto-linux-unix-bash-shell-setup-prompt.html
To set this as default in cygwin:
open bash.bashrc, for me that was in C:\tools\cygwin\etc\bash.bashrc
Find the variable PS1 and change the lower case w to an upper case
PS1='\[\e]0;\w\a\]\n\[\e[32m\]\u#\h \[\e[33m\]\W\[\e[0m\]\n\$ '
^ this one
Restart your terminal
If you already have a high degree of context, for instance when working in vs code, you could change the entire variable to something very minimalist:
PS1='\[\e]0;\w\a\]\[\e[32m\]\[\e[33m\]\W\[\e[0m\] $ '
Which will produce something like this:

Is it possible to change environment variables within Batch and utilize them without restarting CMD prompt?

I want to setup a system wide environment variable within my batch script script running within the CMD prompt, I have been able to achieve this by calling:
setx MyEnvVar "C:\<Some Path>" /M
However when I do:
echo "MyEnvVar is %MyEnvVar%"
afterwards the statement that outputs at prompt is "MyEnvVar is" although the variable has been setup with setx and I can observe it through looking at the Windows - system properties - environment variables GUI.
I know this is because the CMD prompt has to be restarted for it to pick up the new environment variables however I don't want to stop the execution of my batch script and tell the user to manually restart the CMD prompt window and re-run my script so the environment variables are picked up. Is there some other way of getting around this?
It would be better if I could get around this without utilizing the "call" method and breaking the script to two segments
batchfileA - Code up until and including the call to change the environment variables thereafter utilize call method to call batchfileB
batchfileB- The rest of the original code placed inside batchfileB and called with call method within batchfileA
I had tried using set after the setx and echoed the result and the variable was null so I assumed that the value was not taking because I had to restart the CMD prompt what I forgot was I had enabled DelayedExpansion and had to use ! (exclamation marks) instead of % (percent) signs around my variable names

Result of shell script as build setting

Is it possible to run a shell script and use its result as a user defined macro in Xcode?
Basically I just want the result of a shell script to be put in a variable so it gets set in Info.plist (just like ${EXECUTABLE_NAME} etc.)
For example:
If I add $(/usr/bin/whoami) as a build setting condition (at the bottom of settings of the build configuration) it just sets an empty string.
See this question for a couple of different approaches. All of them require add a "Run Script" build phase.
Assuming a bash like shell, and given an almost complete lack of context for your problem, try
EXECUTABLE_NAME=$( scriptToGetEXEC_NAME )
PRODUCT_NAME=$( scriptToGetPROD_NAME)
The $( ... cmd ... ) construct is called command substitution. What this means is the when the shell processor scans each line of code, if first looks to see if there are any $(...) embedded (and other things to). If there are, it spawns a new shell, executes the code inside, and if any text is returned, it is embedded in the command line and THEN the shell scans the line again, and eventually executes everything from left to right, assuming that the first word will turn into a built-in command or a command in the PATH.
I hope this helps.
P.S. as you appear to be a new user, if you get an answer that helps you please remember to mark it as accepted, and/or give it a + (or -) as a useful answer.

How to set PATH to another variable value with spaces in Windows batch file

I've got a Windows batch script issue that I'm bashing my head against (no pun intended). The problematic script looks like this:
if defined _OLD_VIRTUAL_PATH (
set PATH=%_OLD_VIRTUAL_PATH%
)
When I run it and _OLD_VIRTUAL_PATH is set I get:
\Microsoft was unexpected at this time.
_OLD_VIRTUAL_PATH is a variable that was originally set from PATH and it contains spaces - I'm pretty sure that's the problem. But what's the solution? It runs successfully if I enclose it in quotes, but I don't think the entire value of the PATH variable is supposed to be in quotes.
Your problem here are not the spaces but rather a closing parenthesis. You are probably running a 64-bit system where the Program Files directory for 32-bit applications is Program Files (x86). In a parenthesized block in a batch file, the closing parenthesis ends the block, so the rest of the line causes a syntax error.
You have two ways to fix this:
1) Put the complete set argument in quotes. This causes the closing paren to not be recognized as end of block:
if defined _OLD_VIRTUAL_PATH (
set "PATH=%_OLD_VIRTUAL_PATH%"
)
2) Don't use a block:
if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
Well - I never knew about the defined operation in cmd scripts until just now...
Your script seems to work fine for me - which line exactly is producing the error?
You can also try:
if not "%_OLD_VIRTUAL_PATH%" == "" (
set PATH=%_OLD_VIRTUAL_PATH%
)
And believe me, if you're coming into Windows cmd scripting expecting it to be anything like what you have in bash, your head will be very much in pain, very soon. You might want to look into using some other scripting language (PowerShell, Python, PERL - anything) if cmd scripting isn't an absolute requirement. the biggest thing (maybe the only thing) that cmd scripting has going for it is that it's already installed on every Windows box.

Resources