I am trying to set and view windows enviromental variables using locally defined variables. Actual code I tried.
$strAllowGPU_Group = "TF_FORCE_GPU_ALLOW_GROWTH"
$strAllowGPU_True = "True"
$strUserEnvs = "User"
$strCUDAPath = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\bin"
$strCheckForCUDA = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA"
$strWhat = $env:${strAllowGPU_Group}
[System.Environment]::SetEnvironmentVariable(${strAllowGPU_Group},${strAllowGPU_True}, ${strUserEnvs})
I recceive the following error message.
At C:\Users\pgmrdlm\My Drive (pgmrdlm@gmail.com)\DSLR Notes and backup\Software\Scripts\CudaForPixinsight\CudaForPixinsight.ps1:50 char:13
$strWhat = $env:${strAllowGPU_Group}
~~~~~ Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to
delimit the name. At C:\Users\pgmrdlm\My Drive (pgmrdlm@gmail.com)\DSLR Notes and backup\Software\Scripts\CudaForPixinsight\CudaForPixinsight.ps1:50 char:18
$strWhat = $env:${strAllowGPU_Group}
~~~~~~~~~~~~~~~~~~~~ Unexpected token '${strAllowGPU_Group}' in expression or statement.
- CategoryInfo : ParserError: (:) [], ParseException
- FullyQualifiedErrorId : InvalidVariableReferenceWithDrive
This works, and it does exactly what I want. Create a persistant windows variable:
[System.Environment]::SetEnvironmentVariable('TF_FORCE_GPU_ALLOW_GROWTH','True', 'User')
I know this is nothing but me not coding the variable names correctly, but I appoligise. I just don't have a clue.
Thank you in advance.
Dan
tl;dr
$env:${strAllowGPU_Group}
is invalid syntax: you cannot indirectly access an environment variable this way, via a name stored in another variable (${strAllowGPU_Group}
)
Use Get-Content -ErrorAction Ignore Env:$strAllowGPU_Group
(if you know that the variable to exists, you can omit -ErrorAction Ignore
).
To test if an environment variable whose name is stored in variable ${strAllowGPU_Group}
is defined, use:
Test-Variable Env:${strAllowGPU_Group}
(same as: Test-Variable Env:$strAllowGPU_Group
and
Test-Variable "Env:$strAllowGPU_Group"
)
Fundamentally, what follows $
must be a verbatim identifier, optionally prefixed by a verbatim namespace.
That is, you cannot indirectly refer to a variable, via its name being stored in another variable with this syntax.
Therefore, $env:${strAllowGPU_Group}
cannot work, given that what follows env:
must be a verbatim environment-variable name.
As for the incidental aspect of using {...}
around a variable name in a PowerShell variable reference:
{...}
is only necessary if:
(a) if the name contains unusual characters;[1] e.g.:
${a.b} = 'foo'; ${a.b}
- unusual variable name a.b
requires enclosure in {...}
(b) inside an expandable (double-quoted) string ("..."
), if the characters following the variable name in the string would otherwise be mistaken for being part of the variable name; e.g.:
$var='foo'; "A ${var}l and his money are soon parted."
- without {...}
, PowerShell would try to reference a variable named varl
However, you're free to always use {...}
:
$foo_bar = 'baz'; ${foo_bar}
- $foo_bar
is sufficient, but ${foo_bar}
works too.If you do use {...}
, it must enclose both the namespace prefix[2] (if present) and the variable name:
$env:HOME
is the same as ${env:HOME}
$env:{HOME}
To use variable indirection with environment variables, i.e. to access them via their name being stored in another variable, you must use cmdlets that access the Env:
drive:
To test if an environment variable whose name is stored in $strAllowGPU_Group
(aka ${strAllowGPU_Group}
) exists, use the following:
Test-Path Env:$strAllowGPU_Group
$strAllowGPU_Group
has a non-empty value; if $strAllowGPU_Group
evaluates to $null
(including when no such variable is defined) or the empty string, the command invariably returns $true
.To get the value of the environment variable whose name is stored in variable $strAllowGPU_Group
:
Get-Content -ErrorAction Ignore Env:$strAllowGPU_Group
To set the value of the environment variable whose name is stored in variable $strAllowGPU_Group
:
Set-Content Env:$strAllowGPU_Group 'new value'
Note:
Variable:
drive; for setting and getting variable values indirectly, you may also use the Get-Variable
and Set-Variable
.[1] For the exact rules, see the relevant section of the conceptual "about_Variables" help topic, Variable Names that Include Special Characters
[2] For more information about PowerShell's namespace variable notation, see this answer.