问题
I've seen different kind of problems around, but I'm fighting with this for a whole day, so please give me some help :)
Short story: I have different PATH variable in System Variables panel and cmd. Can't run exe files?
Longer story: I'm trying to install Ruby. Tried with different versions, but the problem is the same: I have my PATH value updated, Ruby is there. BUT when using it from cmd, ruby is not recognized. echo %PATH%
gives different value from the one in Environment Variables panel!
First attachment: Environment Variables panel:
Values for user variables:
C:\Users\morifey\nvmw\nodejs\v0.10.36;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;"C:\Program Files\Intel\WiFi\bin\";"C:\Program Files\Common Files\Intel\WirelessCommon\";"C:\Program Files (x86)\Skype\Phone\";"C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x86";"C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64";"C:\Program Files\nodejs\";C:\wamp\bin\php\php5.5.12;C:\ProgramData\ComposerSetup\bin;"C:\Program Files\TortoiseGit\bin";"C:\Program Files (x86)\Git\cmd";"C:\Program Files\Intel\WiFi\bin\";"C:\Program Files\Common Files\Intel\WirelessCommon\";C:\Users\morifey\AppData\Roaming\npm;C:\Ruby21\bin
Value for system variables:
C:\Ruby21\bin;C:\Users\morifey\nvmw\nodejs\v0.10.36;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;"C:\Program Files\Intel\WiFi\bin\";"C:\Program Files\Common Files\Intel\WirelessCommon\";"C:\Program Files (x86)\Skype\Phone\";"C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x86";"C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64";"C:\Program Files\nodejs\";C:\wamp\bin\php\php5.5.12;C:\ProgramData\ComposerSetup\bin;"C:\Program Files\TortoiseGit\bin";"C:\Program Files (x86)\Git\cmd";"C:\Program Files\Intel\WiFi\bin\";"C:\Program Files\Common Files\Intel\WirelessCommon\";"C:\Users\morifey\AppData\Roaming\npm";%SystemRoot%\system32;%SystemRoot%
I compare them to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment - they are all the same.
BUT I run cmd and use echo %PATH%
. Results:
C:\Users\morifey\nvmw\nodejs\v0.10.36;C:\ProgramData\Oracle\Java\javapath;C:\Win
dows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPow
erShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Int
el\WirelessCommon\;C:\Program Files (x86)\Skype\Phone\;C:\Program Files (x86)\In
tel\OpenCL SDK\3.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64;C
:\Program Files\nodejs\;C:\wamp\bin\php\php5.5.12;C:\ProgramData\ComposerSetup\b
in;C:\Program Files\TortoiseGit\bin;C:\Program Files (x86)\Git\cmd;C:\Program Fi
les\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Users
\morifey\AppData\Roaming\npm
Ruby is missing! It's the same for both run as administrator and not (actually I have single administrator user).
I've tried setting path (via set or setx), changing both registries AND environmental variables - nothing is working. I've tried adding quotes ("
) in paths that have spaces - no difference.
Except if I run cmd as administrator and use setx PATH "%PATH%;C:\Ruby21\bin"
! Then, echo %PATH%
returns the real (updated) path, and I am able to run ruby
ONLY in this cmd. If I close it, and reopen it again as admin - changes are lost.
Please give me any kind of advise how to deal with this? I just need to run Ruby :)
Windows 7 Ultimate, Service Pack 1, 64-bit; Downloaded Ruby (from http://rubyinstaller.org/downloads/) - Ruby 2.2.2 (32 & 64 bit), Ruby 2.1.6 (32 & 64 bit) - results are all the same.
Edit: After few guys said I don't need quotes, I've removed them, and placed exactly what @eryksun said. This is the result:
C:\Users\morifey>echo %PATH%
C:\Users\morifey\nvmw\nodejs\v0.10.36;C:\ProgramData\Oracle\Java\javapath;C:\Win
dows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPow
erShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Int
el\WirelessCommon\;C:\Program Files (x86)\Skype\Phone\;C:\Program Files (x86)\In
tel\OpenCL SDK\3.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64;C
:\Program Files\nodejs\;C:\wamp\bin\php\php5.5.12;C:\ProgramData\ComposerSetup\b
in;C:\Program Files\TortoiseGit\bin;C:\Program Files (x86)\Git\cmd;C:\Program Fi
les\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Users
\morifey\AppData\Roaming\npm
It's pretty weird some of the inputs are repeating:
C:\Program Files\Intel\WiFi\bin\;
C:\Program Files\Intel\WiFi\bin\;
C:\Program Files\Common Files\Intel\WirelessCommon\;
C:\Program Files\Common Files\Intel\WirelessCommon\;
C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x86;
C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64;
despite they are not like that in the lines I've pasted in the System Variables Path!
Update - I've used PowerShell and this script to check if there is a repetition in the system variables. I'm uploading image with the result. It's pretty strange that the path is exactly what should be, but as you can see, in CMD I see different thing!
Update - Today I tried running Ruby from PowerShell - all worked out. So it seems like only CMD doesn't know what's going on! And just to remind you - rebooting does not help! :)
回答1:
Turned out to be an issue with a bat file that run each time I started cmd
, and it modified it's variables! Thanks to @eryksun and @ılǝ - it seems that in the registry (HKCU\Software\Microsoft\Command Processor\AutoRun
) you might have something like that. My problem was with nvmw package (https://www.npmjs.com/package/nvmw) that when installed, created this .bat file and stored my current PATH variable. Then it was setting it to the cmd every time I use it, and so it never got updated.
You can see the issue I've created here: https://github.com/nanjingboy/nvmw/issues/5
SHORT STORY: check your HKCU\Software\Microsoft\Command Processor\AutoRun
, and DO NOT USE NVMW package!
回答2:
If your system variable PATH length is longer than some value, it is truncated in cmd prompt. According to this answer this value is 2047. Remove duplicates and trim your path, you will see that both variables will be same.
回答3:
When you use SET operand, it changes environment variables only of current console, it is that what it for. To change environment variables permanent, you should use command SETX. And reboot windows. The Technicaly, you can not reboot, just restart all services, but easily reboot.
回答4:
I do software packaging for automatic deployment, and sometimes there are applications that need their folder setup in %PATH% and for that I use this Powershell script. It checks to see if the folder is there already (so you won't have duplicates) and also removes it if needed (ie for silent uninstall).
You use ADD-PATH to add a folder and REMOVE-PATH to remove it. Works like a charm.
#REQUIRES -Version 3.0
<#
.SYNOPSIS
A script to add or remove folders to %PATH%
.DESCRIPTION
It contains 2 functions, one for adding and one for removing. It reads the registry and does the modifications there.
.NOTES
File Name : AddRemovePath.ps1
Author : Iulian Dita (iulian.dita@gmail.com)
Prerequisite : PowerShell V3 over Vista and upper.
Copyright 2015 - Iulian Dita
.LINK
Script located at:
\\%server%\dsm2$\Work\Master\Projects\29532\Extern$
.VERSION
0.7
.VERSION_HISTORY
0.1 Initial version
0.2 Bug fixes
0.3 Cosmetic fixes, automatic removal of preceding ";"
0.4 Fixed double entries
0.5 Kill Explorer and CMD processes before making any modifications
0.6 Check if folder to be removed already exists in PATH
Escaping special characters no longer needed for the removal function
0.7 Cleaned the code and removed some syntax missmatches
Included the sendmessage function to avoid killing the explorer task
Used [reges]::escape() to avoid running into troubles with the path-string and -match methode
Contributed by Maik Krammer
#>
if (-not ("win32.nativemethods" -as [type])) {
# import sendmessagetimeout from win32
add-type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}
$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero
function global:ADD-PATH
{
[Cmdletbinding()]
param (
[parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)]
[string] $Folder
)
# See if a folder variable has been supplied.
if (!$Folder -or $Folder -eq "" -or $Folder -eq $null) {
throw 'No Folder Supplied. $ENV:PATH Unchanged'
}
# Get the current search path from the environment keys in the registry.
$oldPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
# See if the new Folder is already in the path.
if ($oldPath | Select-String -SimpleMatch $Folder){
return 'Folder already within $ENV:PATH'
}
# Set the New Path and add the ; in front
$newPath=$oldPath+';'+$Folder
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop
# Show our results back to the world
return 'This is the new PATH content: '+$newPath
# notify all windows of environment block change
[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}
function global:REMOVE-PATH {
[Cmdletbinding()]
param (
[parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)]
[String] $Folder
)
# See if a folder variable has been supplied.
if (!$Folder -or $Folder -eq "" -or $Folder -eq $NULL) {
throw 'No Folder Supplied. $ENV:PATH Unchanged'
}
# add a leading ";" if missing
if ($Folder[0] -ne ";") {
$Folder = ";" + $Folder;
}
# Get the Current Search Path from the environment keys in the registry
$newPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
# Find the value to remove, replace it with $NULL. If it's not found, nothing will change and you get a message.
if ($newPath -match [regex]::Escape($Folder)) {
$newPath=$newPath -replace [regex]::Escape($Folder),$NULL
} else {
return "The folder you mentioned does not exist in the PATH environment"
}
# Update the Environment Path
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop
# Show what we just did
return 'This is the new PATH content: '+$newPath
# notify all windows of environment block change
[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}
# Use ADD-PATH or REMOVE-PATH accordingly.
#Anything to Add?
ADD-PATH "%_PATH_TO_BE_ADDED%"
#Anything to Remove?
ADD-PATH "%_PATH_TO_BE_REMOVED%"
I didn't create this script from scratch, I found pieces on line and adapted them to my needs.
EDIT: I updated the code a bit, you no longer have to escape the backslashes or care about ; in front, and also other useful stuff.
回答5:
Could be an issue with the Command Prompt autorun (command prompt setting the PATH on run): https://superuser.com/questions/727316/error-in-command-line-the-system-cannot-find-the-path-specified
来源:https://stackoverflow.com/questions/30685194/system-variable-path-is-different-in-command-prompt