2

I don't understand this. So currently my system environment variable named "PSModulePath" looks like this:

%ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules

Now observe the following PowerShell script:

$envarname = "PSModulePath"
$envar = (get-item env:$envarname).Value
[Environment]::SetEnvironmentVariable($envarname, $envar + ";C:\Expedited", "Machine")

All it should be doing is adding the path "C:\Expedited" to the PSModulesPath environment variable, right? Well, after running this script as administrator, the PSModulePath environment variable changes into this:

C:\Users\Username\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules;C:\Expedited

Notice how:

  1. There were originally two paths, each of which contained percentage signs (variables) in the original, but afterward they all changed directly into hard-coded paths.
  2. The "C:\Users\Username\Documents\WindowsPowerShell\Modules" path sprung out of nowhere (it wasn't in the original!)

I don't have any idea why either of these two things happened. When adding a path to this variable, I would like to keep it as close to the original as possible, not make all these other changes. Is there any way to preserve the percentage signs that were lost? How do I edit this environment variable correctly from within PowerShell?

2
  • "C:\Users\Username\Documents\WindowsPowerShell\Modules" - This would only exist in the user's PATH variable. It appears you are modifying the user's PATH variable instead of the system's PATH variable hence the difference. This question has an answer that explains the differences.
    – Ramhound
    Commented Jul 16, 2018 at 19:55
  • 1
    @PimpJuiceIT, just open System Properties\Advanced\Environment Variables and take a look in there yourself. If you use the actual UI, or even check the corresponding registry entry, you can see the percentage signs in the text string. The problem is that I cannot get the string with the percentage signs using PowerShell for some reason; they always get converted to hard-coded paths and I don't know why. Commented Jul 17, 2018 at 17:06

4 Answers 4

3

PowerShell - Get OS Environmental Variables without Expanding

You can use the Get-Item cmdlet with the -path parameter and then pass that the path of the registry key containing the PSModulePath environmental variable.

You can then use the RegistryKey.GetValue Method along with DoNotExpandEnvironmentNames to get the string value of the PSModulePath environmental variable without expanding it.


PowerShell

$envarname = "PSModulePath"
$regkey    = Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$envar     = $regkey.GetValue($envarname, "", "DoNotExpandEnvironmentNames")
ECHO $envar

Note: You will want to be sure you run this from administrator elevated PowerShell command prompt or ISE screen for it to work correctly.

enter image description here


Further Resources

1
  • 1
    jippyjoe4 - This explains why and gives a way to get the OS Environmental Variables without expanding other environmental variables within their values to retain the percent sign. In case it's not clear as to why explicitly though, it's because the other variables within that variable are being expanded so this is a way to prevent with simple to follow code that's not very complex. Commented Jul 17, 2018 at 23:17
1

Environment variables expansion has been tackled in other answers, but as to why "C:\Users\Username\Documents\WindowsPowerShell\Modules" appears out of nowhere:

PSModulePath is a tricky beast. It does not act as others environment variables.

Outside of Powershell, like any other environment variable, if it exists both in the user's and the machine's environment, the machine's one is discarded.

But inside of Powershell, PSModulePath is a concatenation: the user one + the computer one. (A bit like "Path", but funnily enough, "Path" works the other way round: computer THEN user).

The default machine PSModulePath is "%ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\windowspowershell\v1.0\Modules". If you define a machine PSModulePath that does not contain those two paths, Powershell automatically adds them.

(There are two paths because the modules in %SystemRoot% are compatible with both 32 and 64 bits version of Powershell, whereas those in %ProgramFiles% are not (the trick being that %ProgramFiles% resolves to "Program Files (x86)" for the 32 bits version).)

There is a default PSModulePath for the user too, and it's %USERDOC%\WindowsPowerShell\Modules. But it would be too simple if it acted as its machine counterpart: if the user PSModulePath is not defined, then from within Powershell, its value is set to %USERDOC%\WindowsPowerShell\Modules, that's your 'it comes out of nowhere'.

Now if PSModulePath is defined for the user, its value is just what is defined, and %USERDOC%\WindowsPowerShell\Modules is not added.

I don't know if I'm clear. But I've been bitten by a PSModule problem recently, and I can't seem to find that technical information anywhere.

(Final note: I won't give the details, but all I wrotehere is valid fo Windos Powershell only (v5). Powershell7 adds new paths.)

0

You are doing extra steps that are not really needed for your end goal. Just use the default as shown in the MS guidance.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-6

So, based on the above article, you should only need that last example, or just one line, by using the built-in default / automatic environment variables.

[System.Environment]::SetEnvironmentVariable("PSModulePath", $Env:PSModulePath + ";C:\Expedited","Machine")
1
  • You're right, that method is simpler than my code, but it still results in the same two undesired effects I listed in my original question. Do you have an explanation for those? Commented Jul 17, 2018 at 0:55
0

The environment settings are available in control panel

  1. click start
  2. Type "environment"
  3. Select either "Edit system environment variables" or "Edit environment variables for your account"
  4. select PSModulePath and click "Edit" and "New"
  5. Type or paste the path you need. (Had to add %UserProfile%\OneDrive\WindowsPowerShell\Modules to make sure the modules in my OneDrive backed documents folder got included).

After this log off and on to have the settings catch.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .