Changing a value in the Path environment variable - powershell

My company uses a program that breaks when Java is updated. This is due to the program install (I assume) placing a static path to Java in the Path environment variable. For example, the current Path variable in question is C:\Program Files (x86)\Java\jre1.8.0_171\bin\client, but if Java is updated and the program is re-installed, the Path variable will update to include C:\Program Files (x86)\Java\jre1.8.0_181\bin\client.
I was able to find exactly what I needed (I think) here https://blogs.technet.microsoft.com/heyscriptingguy/2007/11/08/hey-scripting-guy-how-can-i-remove-a-value-from-the-path-environment-variable/, but that code is for Powershell 2.0 and doesn't work on Windows 10.
Is this still possible in Windows 10?

You can use the System.Environment class to modify your environment variables machine-wide:
# get the PATH and split it up
$PATH = [Environment]::GetEnvironmentVariable('PATH', 'Machine') -split ';'
# filter out the JRE paths
$PATH = $PATH -notmatch 'java\\jre'
# get any real JRE paths
$PATH += (Get-Item -Path "${Env:ProgramFiles(x86)}\Java\jre*\bin\client").FullName
$PATH = $PATH -join ';'
[Environment]::SetEnvironmentVariable('PATH', $PATH, 'Machine')
Note: You will need to run your shell elevated to execute these commands.

Java is not a Windows issue, and therefore TechNet will not help you. There is a fix below.
Windows 10 and Windows 8:
Open the Legacy Control Panel
Click the Advanced system settings link.
Click Environment Variables. In the section System Variables, find the PATH environment variable and select it.
Click Edit.
If the PATH environment variable does not exist, click New.
In the Edit System Variable (or New System Variable) window, specify the value of the PATH environment variable.
Click OK.
Close all remaining windows by clicking OK.
Reopen the PowerShell window, and run your Java code.
Source: https://www.java.com/en/download/help/path.xml

Related

How to permanently remove a UNC path from $env:PSModulePath for PowerShell?

Where I work, users have their folders redirected to a UNC path to save data. This seems to have affected my PowerShell because every time I start up powershell, it attempts to load modules from the UNC path and it takes a long time. This also affects how I use cmdlets because it tries to search the UNC path for cmdlet context.
When I look at the output of $env:PSModulePath I can see the UNC directory. But it doesn't show up in System's Environment Variables dialog editor.
How can I get rid of this so that Powershell doesn't keep looking for module support from the UNC directory? I understand that I can edit an existing sessions $env:PSModulePath, but I want it gone forever.
The Microsoft documentation page about_PSModulePath explains it. By default, PowerShell builds the $env:PSModulePath value by concatenating:
The user's "Documents" folder, likely the UNC path you are mentioning.
The contents of the PSModulePath system environment variable.
You can find out the path of the "Documents" folder as follows:
[Environment]::GetFolderPath('MyDocuments')
If you define a user-level environment variable PSModulePath in addition to the system environment variable PSModulePath, it will replace your "Documents" folder in $env:PSModulePath, which won't contain the UNC path anymore.
To permanently change the PSModulePath environment variable, you can use the .NET method SetEnvironmentVariable on the System.Environment class.
Example:
[Environment]::SetEnvironmentVariable("PSModulePath", "Some_Path", "Machine")
Keep in mind, this will overwrite what you had before on this variable. So make sure before you run the method as the PSModulePath will certainly have paths that you might need.
Also, if your company is using GPOs to set the PSModulePath variable, then the only way to remove the UNC path is to talk to your administrator that handles that.
I don't know why it is not shown in your system variables GUI. You should be able to remove it with something along these lines:
$yourvalueyouwanttodelete = 'somepath'
$oldval = [environment]::GetEnvironmentVariable("PSModulePath")
$arr_oldval = $oldval -split ";"
$arr_newval = $arr_oldval | ? {$_ -ne $yourvalueyouwanttodelete}
$newval = $arr_newval -join ";"
[environment]::SetEnvironmentVariable("PSModulePath", $newval)
The way I resolved this was to set the Module Path in the All users profile
For me $PROFILE.AllUsersAllHosts returned:
C:\Program Files\PowerShell\7\profile.ps1
I created that file and added the following:
$ModulePath = "c:\program files\powershell\7\Modules"
[Environment]::SetEnvironmentVariable("PSModulePath", $ModulePath)
I ran into the same issue after removing PowerShell 7 from my device. What appears to be happening is that the PSModulePath variable to My Documents is removed from the environment variables under Advanced System Settings. Powershell then uses the UNC path, which is configured by group policy.
The solution, that worked for me was to add a new Environment Variable called PSModulePath with the value of C:\Users\YourUserNameHere\Documents. Now powershell has a place to look for those PS Modules.

How to change PowerShell default module installation folder?

Is there a way to change PowerShell module installation folder (the folder that modules are placed after Install-Module)?
This is why I want to do this:
I'm on Windows 10, PowerShell 5.1.17763.503
My default installation folder is Documents\WindowsPowerShell\Modules
My Documents folder have been moved to a location containing , symbol (corporate policies)
PS has a bug loading .ps1 that contain classes and have , in the file path (similar to this issue.)
What I've tried:
I thought the installation folder is the first folder in the $env:PSModulePath and I can change it. When I've opened "Edit System Environment Variables" I saw the installation folder is not in the $env:PSModulePath. It's automatically added on the variable when you start PowerShell.
There is no way to change the behaviour of Install-Module so it installs modules in a custom path.
However, You can use Install-Module [...] -Scope AllUsers to install the modules for all users. This would install the modules in $env:ProgramFiles\PowerShell\Modules, but this operation requires elevated permissions (a.k.a. Local Administrator rights).
If you download and install modules to a custom path yourself (or use an alternative implementation to Install-Module), you can modify $env:PSModulePath as you wish.
You can use a profile to patch the $env:PSModulePath every time you start a PowerShell session by adding this to one of your profiles:
# Prepend custom module path.
$env:PSModulePath = ((#("C:\mymodulepath") + ($env:PSModulePath -split ";")) -join ";")
From Modifying the PSModulePath Installation Path
To add paths to this variable, use one of the following methods:
To add a temporary value that is available only for the current session, run the following command at the command line:
$env:PSModulePath = $env:PSModulePath + ";c:\ModulePath"
To add a persistent value that is available whenever a session is opened, add the following command to a Windows PowerShell profile:
$env:PSModulePath = $env:PSModulePath + ";c:\ModulePath"
For more information about profiles, see about_Profiles in the
Microsoft TechNet library.
To add a persistent variable to the registry, create a new user environment variable called PSModulePath using the Environment
Variables Editor in the System Properties dialog box.
To add a persistent variable by using a script, use the SetEnvironmentVariable method on the Environment class. For example,
the following script adds the "C:\Program Files\Fabrikam\Module" path
to the value of the PSModulePath environment variable for the
computer. To add the path to the user PSModulePath environment
variable, set the target to "User".
$CurrentValue = [Environment]::GetEnvironmentVariable("PSModulePath", "Machine")
[Environment]::SetEnvironmentVariable("PSModulePath", $CurrentValue + ";C:\Program Files\Fabrikam\Modules", "Machine")

wget not found by PowerShell script?

I have an old notebook with Windows 7 64-bit that executes a PowerShell script perfectly every Sunday. Unfortunately it starts to crash as soon as the load increases and I decided to get a new PC. On this PC I previously installed Windows&nbspe;10 Pro 64-bit and even here the script was executed every Sunday. Due to the update policy of Microsoft I removed Windows 10 from the new PC and installed Windows 7 64-bit. But now the same script crashes as it does not find wget:
$wg = Start-Process wget.exe -wait -NoNewWindow -PassThru -ArgumentList $argList
Gnu Wget is installed correctly (I think). It is placed at:
C:\Program Files (x86)\GnuWin32\bin\wget.exe
It is even entered in the registry under HKEY_LOCAL_MACHINE → SOFTWARE → Wow6432Node → GnuWin32|Wget|1.11.4-1|setup|InstallPath: C:\Program Files (x86)\GnuWin32.
But despite this if I open the CMD console and enter wget (or wget.exe) I get:
The order "wget" is either misspelled or could not be found.
What do I have to do that PowerShell finds wget constantly even after a restart of the PC? Even e.g. Notepad++ cannot be found by the CMD console despite it is installed properly(?). What's wrong here?
If you want to be able to run a command without specifying its path you need to add the directory it resides in to the PATH environment variable. The install path in the SOFTWARE branch of the registry has nothing to do with it.
To add a directory to the PATH for the current and all future sessions you need to do something like this:
$dir = "${env:ProgramFiles(x86)}\GnuWin32\bin"
# set PATH environment variable for current session
$env:Path += ";${dir}"
# set PATH environment variable for future sessions
$path = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
$path += ";{$dir}"
[Environment]::SetEnvironmentVariable('PATH', $path, 'Machine')
Note, however, that the second step (setting the variable for future sessions) only works correctly if there are no Windows environment variables (%something%) used in $path, because the method saves the value as a REG_SZ in the registry. Windows only expands environment variables in the PATH variable if it's stored as a REG_EXPAND_SZ value.
If you do have regular Windows environment variables somewhere in $path you must manually write the value to the registry with the correct type.
$key = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
Set-ItemProperty -Path $key -Name 'Path' -Value $path -Type ExpandString
Addendum:
All of the above applies only if you want to do this programmatically, of course. For a manual approach you can always edit the environment variables via the GUI and restart PowerShell.

Powershell add to path, temporarily

I'm trying to write a simple PowerShell script to deploy a Visual Studio ASPNET Core 1 project.
Currently, in a batch file i can say
Path=.\node_modules\.bin;%AppData%\npm;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Web\External;%PATH%;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Web\External\git
That will modify the path variable for the duration of the session... for the life of me I can't figure out how to do this simple thing in powershell.
Can someone help me translate this into powershell?
TIA!
Option 1: Modify the $env:Path Variable
Append to the Path variable in the current window:
$env:Path += ";C:\New directory 1;C:\New directory 2"
Prefix the Path variable in the current window:
$env:Path = "C:\New directory 1;C:\New directory 2;" + $env:Path
Replace the Path variable in the current window (use with caution!):
$env:Path = "C:\New directory 1;C:\New directory 2"
Option 2: Use the editenv Utility
I wrote a Windows command-line tool called editenv that lets you interactively edit the content of an environment variable. It works from a Windows console (notably, it does not work from the PowerShell ISE):
editenv Path
This can be useful when you want to edit and rearrange the directories in your Path in a more interactive fashion, and it affects only the current window.
You can just use $env:Path, but if you're anxious that that isn't explicit enough, you can use System.Environment.SetEnvironmentVariable():
[System.Environment]::SetEnvironmentVariable('Path',$Value,[System.EnvironmentVariableTarget]::Process);
And GetEnvironmentVariable() can explicitly retrieve:
[System.Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Process);
[System.Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Machine);
[System.Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::User);

adding cygwin bin directory to powershell path environment variable ... cygwin within powershell

Powershell is great for scripting. But when it comes to everyday use, certain things can be a huge PITA!!
so i thought it would be great if i could do something like this in my profile.ps1:
$env:path = "$($env:path);c:\cygwin\bin"
to get access to utilities like tar, zip, etc... but this doesn't work. The variable looks right when i do:
PS > $env:path
but when i try to do, say,
PS > unzip foo.zip
i get a command not found type error.
WTF PowerShell!?
edit: great answers! I looked at it with fresh eyes this morning and realized that I just needed to spell 'cygwin' correctly! now I don't have to switch back and forth between two consoles. It should be noted for anyone who uses this tip that your path in powershell is evaluated in order - if you put c:\cygwin\bin at the end of the $env:path variable, it will be searched last, so it won't interfere with existing powershell aliases / cmdlets.
It worked for me:
To set your profile:
$command = '$env:path = $env:path + ";C:\Program Files\Notepad++"'
$command | Out-File -FilePath $PROFILE -Append -Encoding UTF8
Or just the current shell:
$env:path = $env:path + ";C:\Program Files\Notepad++"
Using $env:path to add the cygwin bin to PATH should work as long as you are trying to use it in the same Powershell session. If you open a new console or if you close and open Powershell, it will not be persisted. Otherwise, what you are doing should work. Make sure you are indeed adding the correct path. If you want to persist the changes, add the line to your $profile.
Also, try using the Mingw / Msys / Msysgit utils. I find Mingw to be more lightweight than cygwin ( if you are using cygwin just to get some of these utils.)
PowerShell by default is only going to modify its local copy of PATH. When you run an external command, they aren't going to see the local environment variables.
Per this TechNet article, you can fall back to the .NET static method SetEnvironmentVariable to do this at the user level if you want this to be a permanent change:
[Environment]::SetEnvironmentVariable("TestVariable", "Test value.", "User")