Deleting environment variables doesn't work - windows

Why deleting an environment variable with reg delete HKCU\Environment /F /V TestVar in Windows 7 Professional removes it from the registry, but the variable still exists?
Here are the details: I created the following 3 .cmd files:
Check variable.cmd
echo TestVar = %TestVar%
pause
Set variable.cmd
setx TestVar 123
pause
Delete variable.cmd
reg delete HKCU\Environment /F /V TestVar
pause
Then I follow these steps (double clicking to make sure that I start a new session every time):
Double click on Check variable.cmd and I see that TestVar does not exist
Double click on Set variable.cmd and it says SUCCESS: Specified value was saved.
Double click on Check variable.cmd and it shows the variable value. Good!
Double click on Delete variable.cmd and it says The operation completed successfully.
Double click on Check variable.cmd and it still shows the variable value. Bad!
Click on the Start menu, type environment, click on Edit environment variables for your account to open the Environment Variables dialog box, click OK without changing anything
Double click on Check variable.cmd and the variable does not exist anymore
I can find the value in the registry after step 2, I cannot find it after step 4, but step 5 still finds it. And even if I don't change anything, step 6 really deletes the variable.

Here is the solution to my problem. I don't know if it is the correct solution, but it works for me:
Check variable.cmd
set TestVar
#pause
Set variable.cmd
setx TestVar 123
#pause
Delete variable.cmd
reg delete HKCU\Environment /F /V TestVar
setx DummyVarUsedToDelete ""
reg delete HKCU\Environment /F /V DummyVarUsedToDelete
#pause
setx cannot be used to delete a variable, as explained here, but it does the missing broadcasting after a variable has been removed from the registry with reg delete.
EDIT
I added a line to delete the DummyVarUsedToDelete from the registry. This will not be broadcasted, but it is a small temporary problem.

You can use setx to delete an environment variable, this will broadcast the correct message:
setx TestVar ""
reg delete HKCU\Environment /F /V TestVar
(As discussed in the comments, using setx by itself will leave an empty entry behind in the registry, which should be deleted for the sake of consistency.)

The registry is read at boot. When a program is started it gets a copy of it's parent's environment, usually Explorer.exe's environment.
As the comment says, explorer (or any other graphical program that acts on the message) if it gets a message from some other program (like setx) warning it that the registry has been changed, rereads the registry.
The answer is simple
Use set and setx on sequential lines.

DELETING SYSTEM PATH VARIABLE
Method 1:
set var = C:\Users\mahidhai\cygwin64\usr\local\bin
REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V var
In my case , it didn't work even though i ran as administrator .
Command prompt displays error registry key not found
In such case go directly to registry keys file
Method2:
Go To register editor .
Run -> regedit
NAvigate to
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
Edit directly the register key, by clicking on the register key name .
This should work fine
Method 3:
Sometimes not updated windows could be the issue . Check if any updates available . If so update immediately

Related

Batch scripting - adding a new path via registry command (reg add) does not add it to path

I am currently working on a batch script and would like to add new paths to the system environment variables via registry command. Here is my current code:
set newPath=%path%;%NODE_MODULES_DIR%;%NODE_MODULES_DIR%\electron\dist
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Sessions Manager\Environment" /v Path /t REG_EXPAND_SZ /d "%newPath%" /f
call logoff
I do a reg add with new paths. And as I understand, since changes will not take effect until after a logout/restart, I added call logoff to force user to log out.
Problem is when I log back in, I still can't see my new paths under system environment variables.
I do not want to use the setx command because of the 1024 limitation.
Can someone help? Thanks!!
Found what's wrong already.
Turns out that the HKEY_LOCAL_MACHINE path is incorrect.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Sessions Manager\Environment
should be
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
(Session Manager instead of Sessions Manager)
And should've used REG_SZ instead of REG_EXPAND_SZ

How to Open Desktop Properties from CMD?

First post here..
I'm writing a program and I need to change the location of the Desktop from Java, (or CMD).
Is there a CMD command that will open the Desktop properties? (where you can modify the location of the desktop)
Thanks,
You can change the location in the registry.
The following batch file example should set the location to %USERPROFILE%\Desktop, (which is the default).
#Echo Off
Reg Add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Desktop" /V "Path" /T REG_EXPAND_SZ /D "%%USERPROFILE%%\Desktop" /F >Nul
I'll leave it to you to change it to a single cmd.exe command if you'd prefer to do it at the Command prompt or if you think changing the registry another way would be easier for you.
You can enter any valid UNC name or mapped drive in the value of this entry. Just remember that as this is an EXPAND string, you should double up the percent characters if using variables you want to expand when accessed.

Command line to remove an environment variable from the OS level configuration

Windows has the setx command:
Description:
Creates or modifies environment variables in the user or system
environment.
So you can set a variable like this:
setx FOOBAR 1
And you can clear the value like this:
setx FOOBAR ""
However, the variable does not get removed. It stays in the registry:
So how would you actually remove the variable?
To remove the variable from the current environment (not permanently):
set FOOBAR=
To permanently remove the variable from the user environment (which is the default place setx puts it):
REG delete HKCU\Environment /F /V FOOBAR
If the variable is set in the system environment (e.g. if you originally set it with setx /M), as an administrator run:
REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOOBAR
Note: The REG commands above won't affect any existing processes (and some new processes that are forked from existing processes), so if it's important for the change to take effect immediately, the easiest and surest thing to do is log out and back in or reboot. If this isn't an option or you want to dig deeper, some of the other answers here have some great suggestions that may suit your use case.
To remove the variable from the current command session without removing it permanently, use the regular built-in set command - just put nothing after the equals sign:
set FOOBAR=
To confirm, run set with no arguments and check the current environment. The variable should be missing from the list entirely.
Note: this will only remove the variable from the current environment - it will not persist the change to the registry. When a new command process is started, the variable will be back.
This has been covered quite a bit, but there's a crucial piece of information that's missing. Hopefully, I can help to clear up how this works and give some relief to weary travellers. :-)
Delete From Current Process
Obviously, everyone knows that you just do this to delete an environment variable from your current process:
set FOO=
Persistent Delete
There are two sets of environment variables, system-wide and user.
Delete User Environment Variable:
reg delete "HKCU\Environment" /v FOO /f
Delete System-Wide Environment Variable:
REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOO
Apply Value Without Rebooting
Here's the magic information that's missing! You're wondering why after you do this, when you launch a new command window, the environment variable is still there. The reason is because explorer.exe has not updated its environment. When one process launches another, the new process inherits the environment from the process that launched it.
There are two ways to fix this without rebooting. The most brute-force way is to kill your explorer.exe process and start it again. You can do that from Task Manager. I don't recommend this method, however.
The other way is by telling explorer.exe that the environment has changed and that it should reread it. This is done by broadcasting a Windows message (WM_SETTINGCHANGE). This can be accomplished with a simple PowerShell script. You could easily write one to do this, but I found one in Update Window Settings After Scripted Changes:
if (-not ("win32.nativemethods" -as [type])) {
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
[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE,[uintptr]::Zero, "Environment", 2, 5000, [ref]$result);
Summary
So to delete a user environment variable named "FOO" and have the change reflected in processes you launch afterwards, do the following.
Save the PowerShell script to a file (we'll call it updateenv.ps1).
Do this from the command line: reg delete "HKCU\Environment" /v FOO /f
Run updateenv.ps1.
Close and reopen your command prompt, and you'll see that the environment variable is no longer defined.
Note, you'll probably have to update your PowerShell settings to allow you to run this script, but I'll leave that as a Google-fu exercise for you.
From PowerShell you can use the .NET [System.Environment]::SetEnvironmentVariable() method:
To remove a user environment variable named FOO:
[Environment]::SetEnvironmentVariable('FOO', $null, 'User')
Note that $null is used to better signal the intent to remove the variable, though technically it is effectively the same as passing '' in this case.
To remove a system (machine-level) environment variable named FOO - requires elevation (must be run as administrator):
[Environment]::SetEnvironmentVariable('FOO', $null, 'Machine')
Aside from faster execution, the advantage over the reg.exe-based method is that other applications are notified of the change, via a WM_SETTINGCHANGE message - while few applications actually listen to that message and update their environment in response, the Windows (GUI) shell does, so that applications subsequently launched via File Explorer / from the desktop / the taskbar / the Start Menu do see the updated environment.
Delete Without Rebooting
The OP's question indeed has been answered extensively, including how to avoid rebooting through powershell, vbscript, or you name it.
However, if you need to stick to cmd commands only and don't have the luxury of being able to call powershell or vbscript, you could use the following approach:
rem remove from current cmd instance
SET FOOBAR=
rem remove from the registry if it's a user variable
REG delete HKCU\Environment /F /V FOOBAR
rem remove from the registry if it's a system variable
REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOOBAR
rem tell Explorer.exe to reload the environment from the registry
SETX DUMMY ""
rem remove the dummy
REG delete HKCU\Environment /F /V DUMMY
So the magic here is that by using "setx" to assign something to a variable you don't need (in my example DUMMY), you force Explorer.exe to reread the variables from the registry, without needing powershell. You then clean up that dummy, and even though that one will stay in Explorer's environment for a little while longer, it will probably not harm anyone.
Or if after deleting variables you need to set new ones, then you don't even need any dummy. Just using SETX to set the new variables will automatically clear the ones you just removed from any new cmd tasks that might get started.
Background information: I just used this approach successfully to replace a set of user variables by system variables of the same name on all of the computers at my job, by modifying an existing cmd script. There are too many computers to do it manually, nor was it practical to copy extra powershell or vbscripts to all of them. The reason I urgently needed to replace user with system variables was that user variables get synchronized in roaming profiles (didn't think about that), so multiple machines using the same windows login but needing different values, got mixed up.
I agree with CupawnTae.
SET is not useful for changes to the master environment.
FYI: System variables are in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment (a good deal longer than user vars).
The full command for a system var named FOOBAR therefore is:
REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOOBAR
(Note the quotes required to handle the space.)
It is too bad the setx command doesn't support a delete syntax. :(
PS: Use responsibly - If you kill your path variable, don't blame me!
The command in DougWare's answer did not work, but this did:
reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v FOOBAR /f
The shortcut HKLM can be used for HKEY_LOCAL_MACHINE.
setx FOOBAR ""
just causes the value of FOOBAR to be a null string. (Although, it shows with the set command with the "" so maybe double-quotes is the string.)
I used:
set FOOBAR=
and then FOOBAR was no longer listed in the set command. (Log-off was not required.)
Windows 7 32 bit, using the command prompt, non-administrator is what I used. (Not cmd or Windows + R, which might be different.)
BTW, I did not see the variable I created anywhere in the registry after I created it. I'm using RegEdit not as administrator.
You can also create a small VBScript script:
Set env = CreateObject("WScript.Shell").Environment("System")
If env(WScript.Arguments(0)) <> vbNullString Then env.Remove WScript.Arguments(0)
Then call it like %windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR.
The disadvantage is you need an extra script, but it does not require a reboot.
By the way I just figured out how to unset a permanent variable that you've set using setx.
Simply write quotation marks, like:
setx myvar ""
And on next cmd window restart, if you search for the variable
set myvar
There won't be anything set for it.
In PowerShell, the way to delete an Registry value is with the Remove-ItemProperty cmdlet. In this case, the persistent value (for future processes) is removed with:
Remove-ItemProperty HKCU:\Environment FOOBAR
And if you wish to remove it from the current environment, you can just remove it from the Env: "drive" like so:
rm env:\FOOBAR
SETX.exe cannot be used to do this.

How to make permanent system variable using BATCH or VBS?

I am making an installer which will be 100% depending on system variable such as %TEMP% or %Path%, users first double click windows.bat file.
But, How can i setup permanent system variable in Windows XP, Vista, 7, 8 using VBS or BATCH?
I tried with BATCH but in Windows XP, most users do not have setx by default, so i want to avoid using that technique. Is there better way to do that?
C:\Documents and Settings\sun>REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Ses
sion Manager\Environment" /v MyApplicationWillUsetThis /d "C:\WhatEverPathToIncl
udeHereQuestionMark"
The operation completed successfully
C:\Documents and Settings\sun>REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Ses
sion Manager\Environment" /v MyApplicationWillUsetThis /d "C:\WhatEverPathToIncl
udeHereQuestionMark"
Value MyApplicationWillUsetThis exists, overwrite(Y/N)? Y
The operation completed successfully
You can create a REG_SZ value under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment in the registry. The name of the value specifies the name of the environment variable, the value specifies the value of the environment variable.
You can also modify existing values.
In order to modify the registry you can use the RegRead and RegWrite method of the WScript.Shell object. For an example have a look at Manipulating the System Registry.
Edit: You could at first delete the existing value and recreate it afterwards.
REG DELETE "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v MyApplicationWillUsetThis /f
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v MyApplicationWillUsetThis /d "C:\WhatEverPathToIncludeHereQuestionMark"
How to set environment variables from VBScript
Set WshShell = CreateObject("Wscript.Shell")
' set a permanent environment variable %MyVarName% for all users
WshShell.Environment.item("MyVarName") = "MyVarValue"
If the above setting isn't permanent, try this one. This will set a permanent environment variable for all users. You can try System, User, Volatile, and Process categories with the Environment collection.
With WSHShell.Environment("SYSTEM")
.item("MyVarName") = "MyVarValue"
End With
You can also use ExpandEnvironmentStrings to read environment variables or replace them with their values in long command line type strings.
sValue = WshShell.ExpandEnvironmentStrings("%MyVarName%")
To work with the registry try
sRegKey = "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\MyVarName"
sValue = WshShell.RegRead(sRegKey)
' don't write if no change is required.
If sValue <> sNewValue Then WshShell.RegWrite sRegKey , sNewValue

cmd defaults to F: drive

When I open cmd on my laptop it is defaulting to the F: drive. This is troubling me does anyone know how it got that way or how to get it back to where it opens to the C: drive by default?
Use the command
C:
To change to the drive C. It would of course work for any drive letter.
Very minor nit: if you're using Windows 7 you don't need the cmdhere powertoy, it's built in to Explorer.
You just navigate to a directory in Windows Explorer then hold down the shift key and right click. "Open command window here" is one of the selections on the context menu.
When it comes to opening cmd.exe in a specific directory, I just create a shortcut to cmd.exe and then in the shortcut properties I set "Start in:" to the drive/directory I want it to start in.
Using a shortcut allows me to customize the cmd.exe windows depending on what I'm using it for. For normal file editing/viewing I use a 180x60 window and appropriate font, but when I want to read/search log files I have a shortcut that opens a 260x100 window with a smaller font. That way I can view most long log file lines without having to use the horizontal scroll.
http://blog.stevienova.com/2007/04/08/change-your-default-cmd-prompt-path/
Sometimes, your path when you go to start->run, CMD will be something
you don’t want. In active directory or on an NT domain, sometimes your
default home path might be a network drive. This isn’t so good when
you are offline or drop offline after being online. The CMD prompt is
set to a place where you can’t get to.
To change the path, you can edit the registry (at your own risk)
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USERSoftwareMicrosoftCommand Processor] “Autorun”=”c:”
This will change the path to your c: drive.
I believe it defaults to %HOMEDRIVE%\%HOMEPATH% so if you can muck about with those environment variables that might be an option. I can't edit these environment variables on my company's network, so I had to use the AutoRun to change it to something sane.
quick answer: cmd /k c:
long answer to make it "automagical":
http://windowsxp.mvps.org/autoruncmd.htm
In RegEdit.exe I created a String:
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
The value I used for AutoRun was "D:"
On the start screen / menu, type in "cmd", right-click it and select "Open File - Location".
In the opened window, right-Click on "Command Prompt" icon, select "Properties", and edit the "Start In" property to your desired path. I used "C:\" as an example
If you are opening it from a shortcut change the working dir for the shortcut.
In addition to the other answers, there's a nice powertoy for XP called "open command window here." It adds an option to your right-click context menu when you click inside a folder to open a command window using that directory as the starting path.
http://www.microsoft.com/windowsxp/Downloads/powertoys/Xppowertoys.mspx
I ran into a similar issue where cmd would always open up in a particular directory (annoying when running scripts which invoke cmd). The best way to deal with this is to edit your autorun settings. Raymond Chen has a nice article about this here:
http://blogs.msdn.com/oldnewthing/archive/2007/11/21/6447771.aspx
The summary is that when you start a command shell, it checks the autorun registry key, and executes the commands stored there. The registry keys it checks are:
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
and/or
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
Some answers already mentioned AutoRun as a solution.
But that can be very dangerous, as the AutoRun entry will be executed for any new cmd.exe instance (only pipes ignore the AutoRun).
A simple expample that fails:
cd /d E:\myPath
FOR /F "delims=" %%Q in ('dir') do echo - %%Q
With AutoRun=C:, this shows the content of the current path of drive C:
You can still use AutoRun, but it should be a batch script, that checks if it was called interactive, by FOR/F or by drag&drop.
#echo off
REM *** To enable this script, call it by <scriptName> --install
setlocal EnableDelayedExpansion
REM *** ALWAYS make a copy of the complete CMDCMDLINE, else you destroy the original!!!
set "_ccl_=!cmdcmdline!"
REM *** The check is necessary to distinguish between a new cmd.exe instance for a user or for a "FOR /F" sub-command
if "!_ccl_:~1,-2!" == "!comspec!" (
REM ***** INTERACTIVE ****
REM *** %1 contains only data, when the script itself was called from the command line
if "%~1" NEQ "" (
goto :direct_call
)
endlocal
doskey /macrofile="%~dp0\cmdMacros.mac"
echo ********************************************************************
echo * AutoRun executed from "%~f0"
echo * Macros loaded from "%~dp0\cmdMacros.mac"
echo ********************************************************************
cd /d C:\myPath
) ELSE (
REM *** Called by a FOR command, by an explorer click or a drag & drop operation
REM *** Handle PROBLEMATIC Drag&Drop content, if necessary
endlocal
)
exit /b
:direct_call
if "%~1" == "--install" (
reg add "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v "AutoRun" /t REG_SZ /d "%~f0"
exit /b
)
if "%~1" == "--show" (
reg query "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v AutoRun
exit /b
)
if "%~1" == "--remove" (
reg DELETE "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v AutoRun /f
)
exit /b

Resources