Nested Environment Variables Cause Error Message

I've got a System environment variable %USERTEMP% which is defined as %USERPROFILE%\TEMP
I use this to stop my desktop becoming a dumping ground for temp stuff.

Windows Explorer.exe and commandline.exe handle this environment variable fine, but it results in an error message in Directory Opus.

When do you see the error messages? What are you doing when they happen?

What are the exact error messages that you see?

(A screenshot can be useful as it gives us both the full text and sometimes the ability to tell if it is Opus or a part of Windows displaying the message, from how the dialog looks.)

PS: Based on https://stackoverflow.com/questions/3594846/limits-on-windows-environment-variable-nesting I am not sure Windows really supports nested environment variables, except purely by accident in a subset of cases, which don't include the one you're attempting. USERTEMP is alphabetically after USERPROFILE but the dependency you're creating is the other way around.

So my guess is this is not supported by Windows, but you're getting lucky in some cases (maybe things that happen to scan for env-vars twice by accident, due to a chain of API calls) and running into problems in others.

Opus correctly converts it to %USERPROFILE%\TEMP in the toolbar, but throws the error below. If I type %USERPROFILE%/TEMP directly it works.

Testing the same thing in a Command Prompt, it doesn't look like it works there either?

It doesn't work either way around (A pointing to B, or B pointing to A):

Are you sure this is really supported by Windows?

It works and it is supported.

image

I also tested it in XYPlorer and FreeCommander and my %USERTEMP% variable works as it should.

If you do that in a command prompt without escaping the % characters, the command prompt expands the current env-vars at the time the set command is run.

Type set fullname and you'll see it is defined as Testy McTest and not %firstname% %lastname%.

That's why the ^ are in the first line of my last screenshot, to escape the % characters when setting the dependent variable, which then does not work as the command prompt does not seem to actually support nested variables.

Ok well I don’t really understand what your doing there all I know is that the scenario I described in my original post works in cmd.exe, Explorer.exe, XYplorer.exe and FreeCommander.exe but it does. not work in Opus.

But I've just demonstrated that it doesn't work in cmd.exe...

You demonstrated that something doesn't work. I am not attempting to do what you've done, tbh I'm not really sure what you're trying to do. Here's what I did:

  • Open System Settings / Environment Variables
  • Make a new system environment variable %USERTEMP% = %USERPROFILE%\TEMP
  • Make use of this new environment variable in CMD, Explorer, XYPlorer, FreeCommander and observe that it works
  • Make use of this new environment variable in Opus and observe that it does not work.

I have not tried the others, but it does not work in CMD:

Based on this and the other things I linked, I don't think it is really supported by Windows at all.

It does work. And it works in CMD, Explorer, XYPlorer, FreeCommander And if you look at the screenshot you posted yourself. You'll see an example of nested Environment variables used in PSModulePath.

image

For some reason Opus doesn't pick up all environmental system variables from the registry. Some of the built-in ones work, so do user-defined ones.

05%20-%20Environment_Variables

System variables including %userprofile% seem to be a bit special (no idea why).

36%20-%20Environment_Variables

Funny enough, these variables work when defined as a User variable:

27%20-%20Environment_Variables

52%20-%20CUsersAlexandertemp

BTW: I find it a bit strange that in reach4thelasers's last screenshot the env var is already expanded.

For completeness: I am on Win7

I think what @leo was getting at, @reach4thelasers, is that nothing reevaluates the final version of the environment variable. Below, you can see I set the fullname variable to firstname lastname. Then I modify the firstname, but you can see fullname remained unchanged.

So, it works, but only the first time the environment variable is set. To a lot of people, including me, these aren't nested environment variables because the inside environment variables (firstname and lastname, in my test below) don't stay stored as an environment variable. Rather, they are immediately resolved (or "de-nested") upon assignment. That's the reason fullname doesn't change from "Mickey Mouse" to "Minni Mouse" but stays set as "Mickey Mouse".

image

%userprofile% works OK in Opus here, and looks like it is working in your screenshot. What's not working for you?

Your %TEMP% example pointing to something different to the System TEMP variable in the screenshot is because there's also user TEMP variable which overrides the system TEMP variable for any process running under your account. (Your temp folder should never be C:\Windows\TEMP (you would not normally even be able to create files there), but that system TEMP variable exists as a fallback for certain contexts. Maybe services running under SYSTEM, although I'd have to look up when it was used.)

PSModulePath is only used by PowerShell. Maybe it has special rules for expanding env-vars multiple times. I think the PATH variable may also have that. But those rules don't apply generally.

I'm still wondering why you think this works in cmd.exe. What was your test?

I am not completely against making Opus expand variables multiple times, but I still need convincing it is the right thing to do. In particular,% characters are valid inside path names, so if we change the rules about how they are expanded then it could cause unexpected changes where path names contain those characters.

In addition, and perhaps most importantly, we expand env-vars by asking Windows to expand them. We don't do it ourselves with custom code. We call the proper API for doing it, ExpandEnvironmentStrings, which applies whatever rules Windows defines to do the expansion(s). Whether that API expands recursively or only once is up to the operating system. If it only does it once, then I do not believe nested env-vars are really supported by Windows, even if it is possible to call the API multiple times until the string stops changing (or some other strategy), and even if a handful of things do that (for whatever reason).

Testing with cmd.exe seems to confirm that nested env-vars are not supported by Windows, and if you create them (outside of special cases) then they will not work in a lot of places, including parts of Windows itself. So they are probably best avoided (outside of special cases), regardless of what Opus or any particular software does.

Yes, sorry, that was a bit confusing. %userprofile% works just fine. What I meant was: system variables, that include %userprofile% in their values don't show up in Opus' list of suggestions. They don't work in the DOS prompt either (Iike in your example). The other variables in my examples do, e.g. cd %test2%.

So I think it's more a Windows problem rather than an Opus bug.

1 Like