SETX not setting system variable when using /M - setx

I am trying to set a persistent system variable. This is for a process in which a batch file refers to the variable, and then edits the variable at the end of the process.
I am using setx with the /M parameter, however, it continues to create the environment variable under the local user instead of the system.
The command I am specifically running is:
setx FN 101 /M
What am I missing?

I did not launch an elevated CMD. Turns out in order for the /M parameter to work, CMD must be run as an administrator.

Related

How to set an env variable with multiline file content in windows command prompt

I have a file say my-file.dat which has multiple lines. I want to set an env variable say MYVAR that will contain the content of my-file.dat.
That is, in windows command prompt, the output of type my-file.dat be same as the output of echo %MYVAR% and with new-line preserved.
In RHEL/MAC, it is typically done like this export MYVAR=$(cat my-file.dat), but how do I do the similar in windows command prompt (not really interested in powershell, but feel free to share examples it might be my backup option)
Following the answer of this Stackoverflow question Multiline text file, how to put into an environment variable I could get a variable to hold the content of my-file.dat. But this variable's scope seems to be the batch file. Even though I run the batch file from the command prompt, I don't see the batch-file's variable is available in the command prompt.
I tried set /P MYVAR=<my-file.dat , but this sets only the first line whereas I want all lines when I echo MYVAR
Pls help.
The technique you use requires delayed expansion, which is not enabled by default. So the code issues setlocal enableDelayedExpansion. But that localizes environment changes. When the script ends there is an implicit endlocal, and the environment is restored to what existed before the setlocal.
The simplest solution is to run the script in a session where delayed expansion is already enabled so that you can remove setlocal enableDelayedExpansion. You can do this simply by running
cmd /v:on from your command line before executing your script.
There is another simple, but ugly option. The implicit endlocal does not occur if your script has a fatal syntax error (I consider this to be a bug in cmd.exe). So you can put the following at the end of your script:
:: Your current script goes here.
:: I'm assuming your script falls through to the end and does not use EXIT /B
call :fatalErr 2>nul
:fatalErr
if
But I discourage you from using this technique if you might be executing your script multiple times - your dead environments will begin to pile up.
Also - please remember that variables are limited to ~8191 characters - your script will fail if the file you are trying to capture exceeds the limit. This is a hard limit of cmd.exe
Update
You could put the cmd /v:on command within your script if you add the /K option. The IF statement tests if delayed expansion is enabled or not. If not, then it reruns the script via cmd.exe with the /K option and /V:ON.
#echo off
if "!!" neq "" cmd /v:on /k "%~f0"
:: rest of your script goes here.

How to use global variable in arguments to setx command in cmd (command line)

Performed
setx /m DESKTOP %UserProfile%\Desktop
Real result
set DESKTOP
DESKTOP=C:\Users\dkurlyanov\Desktop
Desired result
set DESKTOP
DESKTOP=%UserProfile%\Desktop
I'm only interested in the option through the console
Correct answer from "Compo"
setx /m DESKTOP ^%UserProfile^%\Desktop

Is there an equivalent source command in Windows CMD as in bash or tcsh?

I know that in the unix world, if you edit your .profile or .cshrc file, you can do a source ~/.profile or source ~/.cshrc to get the effect on your current session. If I changed something in the system variable on Windows, how can I have it effect the current command prompt session without exiting the command prompt session and opening another command prompt session?
In the usual Windows command prompt (i.e. cmd.exe), just using call mybat.bat did what I wanted. I got all the environment variables it had set.
The dos shell will support .bat files containing just assignments to variables that, when executed, will create the variables in the current environment.
c:> type EnvSetTest.bat
set TESTXYZ=XYZ
c:> .\EnvSetTest.bat
c:> set | find "TESTX"
TESTXYZ=XYZ
c:>
IHTH.
Following example will help you to solve your problem.
env.bat This file is for setting variables. Its contents are given blow.
set name="test3"
test.bat Our main batch file.
call env.bat
call print.bat
pause
Now print.bat batch file to print variables. Its contents given below
echo %name%
I am afraid not, but you can start using Powershell, which does support dot sourcing. Since powershell window is really based on cmd so all your dos command will continue to work, and you gain new power, much more power.
The only way I have found this to work is to launch a new cmd window from my own config window. eg:
#echo off
echo Loading...
setlocal enabledelayedexpansion
call 1.cmd
call 2.bat
...
...
if "%LocalAppData%"=="" set LocalAppData=%UserProfile%\Local Settings\Application Data
SET BLAHNAME=FILE:%LocalAppData%\BLAH
call blah blah
cmd
The last cmd will launch a new cmd prompt with the desired settings exported to the command window.
Here's a workaround for some limited use-cases. You can read-in a file of commands and execute them in-line. For example the calling command file looks like:
echo OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:
echo. ----------------
echo. set-up java
echo. ----------------
echo.
rem call %DEV_SCRIPTS%\setup-java
for /F "tokens=*" %%A in ( %DEV_SCRIPTS%\setup-java.bat ) do (
%%A
)
call %DEV_SCRIPTS%\show-java
:
In the setup-java.bat file you can't use % expansion. You need to use !; e.g.:
set JRE_HOME=!JRE_08!
rem
set JRE_TARGET=!JRE_HOME!
So you are litterally source-ing commands from a text file. You will need to test which commands sourced in this way. It took a few trials just to set some environment variables.
I don't think we can do logic or loops because the command processor scans the file at the start. I am OK just having a simple workaround to reuse shared things like environment definitions. Most other things won't need an actual source command (I am hoping). Good luck.
For example to set VC# vars
C:\Windows\System32\cmd.exe /k "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
Use git bash for windows, it works totally fine!

Setting a system environment variable from a Windows batch file?

Is it possible to set a environment variable at the system level from a command prompt in Windows 7 (or even XP for that matter). I am running from an elevated command prompt.
When I use the set command (set name=value), the environment variable seems to be only valid for the session of the command prompt.
The XP Support Tools (which can be installed from your XP CD) come with a program called setx.exe:
C:\Program Files\Support Tools>setx /?
SETX: This program is used to set values in the environment
of the machine or currently logged on user using one of three modes.
1) Command Line Mode: setx variable value [-m]
Optional Switches:
-m Set value in the Machine environment. Default is User.
...
For more information and example use: SETX -i
I think Windows 7 actually comes with setx as part of a standard install.
Simple example for how to set JAVA_HOME with setx.exe in command line:
setx JAVA_HOME "C:\Program Files (x86)\Java\jdk1.7.0_04"
This will set environment variable "JAVA_HOME" for current user. If you want to set a variable for all users, you have to use option "/m" (or -m, prior to Windows 7).
Here is an example:
setx /m JAVA_HOME "C:\Program Files (x86)\Java\jdk1.7.0_04"
Note: you have to execute this command as Administrator.
Note: Make sure to run the command setx from an command-line Admin window
If you set a variable via SETX, you cannot use this variable or its changes immediately. You have to restart the processes that want to use it.
Use the following sequence to directly set it in the setting process too (works for me perfectly in scripts that do some init stuff after setting global variables):
SET XYZ=test
SETX XYZ test
For XP, I used a (free/donateware) tool called "RAPIDEE" (Rapid Environment Editor), but SETX is definitely sufficient for Win 7 (I did not know about this before).
System variables can be set through CMD and registry
For ex. reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH
All the commonly used CMD codes and system variables are given here: Set Windows system environment variables using CMD.
Open CMD and type Set
You will get all the values of system variable.
Type set java to know the path details of java installed on your window OS.
SetX is the command that you'll need in most of the cases.Though its possible to use REG or REGEDIT
Using registry editing commands you can avoid some of the restrictions of the SetX command - different data types, variables containing = in their name and so on.
#echo off
:: requires admin elevated permissions
::setting system variable
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v MyVar /D MyVal
::expandable variable
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /T REG_EXPAND_SZ /v MyVar /D MyVal
:: does not require admin permissions
::setting user variable
REG ADD "HKEY_CURRENT_USER\Environment" /v =C: /D "C:\\test"
REG is the pure registry client but its possible also to import the data with REGEDIT though it allows using only hard coded values (or generation of a temp files). The example here is a hybrid file that contains both batch code and registry data (should be saved as .bat - mind that in batch ; are ignored as delimiters while they are used as comments in .reg files):
REGEDIT4
; #ECHO OFF
; CLS
; REGEDIT.EXE /S "%~f0"
; EXIT
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
"SystemVariable"="GlobalValue"
[HKEY_CURRENT_USER\Environment]
"UserVariable"="SomeValue"
Just in case you would need to delete a variable, you could use SETENV from Vincent Fatica available at http://barnyard.syr.edu/~vefatica.
Not exactly recent ('98) but still working on Windows 7 x64.

Can I set an environment variable for an application using a shortcut in Windows?

I have a feeling I should be able add a directory to the PATH environment variable on an application-lifetime basis, but I can't find out how to do this. Is it possible to add a parameter to a Windows shortcut that appends a directory to the current value of PATH for use by the application being linked?
As explained here: http://www.labs64.com/blog/2012/06/set-environment-variables-in-windows-shortcut/
you can do it without a bat file too.
Set Target to e.g.:
C:\Windows\System32\cmd.exe /c "SET path=%path%&& START /D ^"C:\Program Files (x86)\Notepad++^" notepad++.exe"
To avoid see the command prompt for a split second before it close again, you should set
Run: Minimized
on the Shortcut tab
(Tested on Windows 7, Windows 10)
Let the shortcut execute a batch file (.cmd), that
Sets the environment variable
execute the app
You use "START" to execute the app, this will start the app in another process, but it will copy the environment. You do not wait for the app to finish.
Now you can exit the batch file.
Should look like this:
#echo off
set path=%path%;C:\My Folder
start "Window Title" "Path to my exe"
Linking directly to a batch file spawns an annoying console that you probably want to avoid. Here's a work-around. The simpler solution is to use the "Start Minimized" option in your link, but on Windows 7 you'll see a momentary console light up your task bar.
start.bat:
#echo off
IF "%1" == "" GOTO Error
IF "%2" == "" GOTO Error
IF NOT EXIST %2 GOTO Error
SET PATH=%1;%PATH%
start %2
GOTO End
:Error
echo Problem!
pause
:End
shortcut target:
MyPath = "C:\MyApp"
Set shell = WScript.CreateObject("WScript.Shell")
cmd = "start.bat " & MyPath & " MyApp.exe"
shell.Run cmd, 0, false
Set env = Nothing
Set shell = Nothing
You can do this with PowerShell easily. PowerShell exposes environment variables using the $env: prefix. For example, I wanted to launch TeamSQL with custom JAVA_HOME and PATH environment variables, so I could connect to a PostgreSQL database. TeamSQL depends on JDK / OpenJDK for this purpose.
First, I downloaded pre-built OpenJDK and extracted the ZIP archive with 7-Zip.
Next, in PowerShell, I ran the following:
$env:JAVA_HOME='C:\Users\TrevorSullivan\Downloads\openjdk\jdk-11.0.2\'
$env:PATH += ';%JAVA_HOME%\bin'
# Launch TeamSQL
& C:\Users\TrevorSullivan\AppData\Local\Programs\TeamSQL\TeamSQL.exe
Store that PowerShell code in a .ps1 file, and you can run it with PowerShell. Because child processes inherit the environment variables from the PowerShell session, your program is good to go.

Resources