In Windows, you can call up the Environment Variables dialog box to edit both the System environment variables and the User environment variables. What happens if you use the %
sign to reference one environment variable from another?
Environment variable processing occurs in several steps.¹
- Core system environment variables:
ALLUSERSPROFILE
,ProgramData
,PUBLIC
,SystemDrive
,SystemRoot
. - System environment variables of type
REG_SZ
. - System environment variables of type
REG_EXPAND_SZ
. - Core user environment variables:
APPDATA
,COMPUTERNAME
,LOCALAPPDATA
,ProgramFiles
,USERPROFILE
. - User environment variables of type
REG_SZ
. - User environment variables of type
REG_EXPAND_SZ
. - Account environment variables:
USERDNSDOMAIN
,USERDOMAIN
,USERNAME
.
The rule is that each step can redefine variables set by a previous step, and variables of type REG_
can depend on variables set by a previous step, but cannot depend on variables set elsewhere within the same step or by a future step.
This means, for example, that you can use %USERPROFILE%
in the definition of a User environment variable of type REG_
,, but not in the definition of a System environment variable.
There is a bonus special rule for the PATH
environment variable: The User definition of the PATH
environment variable is appended to the System definition, rather than replacing it.²
If you have a REG_
between variables at the same step, it is unspecified whether the expansion is the old value or the new value, so don’t do that.³
¹ This is a simplified discussion for the purpose of exposition.
² This special rule also applies to the vestigial LibPath
and Os2LibPath
environment variables.
³ To avoid people taking dependencies on implementation details, I would have enforced the rule more strictly and consistently and said that all REG_
expansions use the value of the variable as defined by previous steps, and any changes made in the same step are not visible. But of course the implementation was written before the realization that people would try to create dependencies among variables in the same group.
Ah, but Japan Windows Commercial Support documents that order in a step and explains it to their customers.
https://social.technet.microsoft.com/Forums/ja-JP/0add404a-4157-416f-bf15-0ad455102d85?forum=Wcsupportja
There is also this limitation with environment variable assignments that I recall from bat-files:
This will output “bar”, not the expected “foobar”.
Has this kind of limitation been retained over the decades for legacy compatibility?
This is just how those ( ) blocks work, use delayed expansion if you need a value set there.
https://devblogs.microsoft.com/oldnewthing/20060823-00/?p=29993
Oh, you are right, this whole thing:
<code>
It correctly prints "foobar".
This was so many years ago, I've forgotten the details.
I think this was covered in the Windows NT Workstation Resource Kit book, that would had been where I had studied this back then, because I looked now in my old Windows NT and Windows 2000 pocket reference books from O'Reilly that I still have left, and it's not mentioned in either of them.
Bat-files of course have a use but they are frustratingly primitive so I started installing ActivePerl on all Windows machines under my control from...