OldAndRetired
OldAndRetired

Reputation: 87

set Windows Enviromental variable with a local powershell variable

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 ([email protected])\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 ([email protected])\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

Upvotes: 2

Views: 275

Answers (1)

mklement0
mklement0

Reputation: 440037

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")


Background information:
  • 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:

      • E.g., $env:HOME is the same as ${env:HOME}
      • By contrast, $env:{HOME} is broken syntax.

Solutions:

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
    
    • Note: This assumes that $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:


[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.

Upvotes: 4

Related Questions