On Windows, how can I use Ruby to permanently set an environment variable? I know I need to change the registry (through the win32ole module?) but I am a novice with regard to scripting the registry.
I understand that I can say ENV['FOO'] = "c:\bar\baz" to set the environment variable FOO for the session. However, I am instead interested in setting environment variables globally and permanently.
I did find the patheditor gem, which works great for permanently altering the Windows PATH. But I want to set other environment variables, for example, JAVA_HOME.
There is a past question about this. The basic gist is to set the variable in the registry via Win32::Registry (like runako said). Then you can broadcast a WM_SETTINGCHANGE message to make changes to the environment. Of course you could logoff/logon in between then too, but not very usable.
Registry code:
require 'win32/registry.rb'
Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
reg['ABC'] = '123'
end
WM_SETTINGCHANGE code:
require 'Win32API'
SendMessageTimeout = Win32API.new('user32', 'SendMessageTimeout', 'LLLPLLP', 'L')
HWND_BROADCAST = 0xffff
WM_SETTINGCHANGE = 0x001A
SMTO_ABORTIFHUNG = 2
result = 0
SendMessageTimeout.call(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 'Environment', SMTO_ABORTIFHUNG, 5000, result)
Thanks to Alexander Prokofyev for the answer.
Also see a good discussion on Windows environment variables in general, including how to set them for the entire machine vs. just the current user ( in HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Control\ Session Manager\ Environment)
You're looking for Win32::Registry :
http://www.ruby-doc.org/stdlib/libdoc/Win32API/rdoc/classes/Win32/Registry.html
For reference, here's how I found it:
http://www.google.com/search?client=safari&rls=en-us&q=ruby+registry&ie=UTF-8&oe=UTF-8
Anyhow, then you will want to do something like:
registry.open("HKEY_WINDOWS_GUNK/path/to/your/key", Win32::Registry::KEY_WRITE) do |reg|
reg[regentry, Win32::Registry::REG_DWORD]=value
end
You might have to create a key first, if it doesn't already exist.
I am pleased to see such a comprehensive set of answers!
It should also be noted that when creating/writing to entries under reserved/system keys (such as HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node on 64-bit Windows operating system) using constant flags such as Win32::Registry::KEY_WRITE and Win32::Registry::KEY_ALL_ACCESS will not exhibit desired behaviour unless the MRI (the Ruby interpreter) instance is started from an "Administrator" kernel context. Starting cmd.exe (Windows shell program) by right-clicking the executable and selecting "Run as Administrator" allows this.
Related
What does % mean in windows environmental variables ?
%SystemRoot%\system32;
%SystemRoot%;
%SystemRoot%\System32\Wbem;
Especially the Path, TMP, TEMP variable values have this sign. There might be other variables also, but I came across only these three.
Do I need to bother about it while setting my own path variables ?
Do I need to bother about it while setting my own path variables ?
Under normal circumstances, no, you don't. You would only do this if you wanted the effective value of PATH to depend on some other environment variable. Even then it is only a convenience, never a necessity.
As a real-world example of when it might be convenient, suppose you've written a program that automates updating the Java SDK to the latest version, so your users don't have to do it by hand. Updating the SDK moves it to a different location, so you probably want to add the new location of the SDK to the path, and remove the old one.
You could do that the hard way, by parsing PATH each time, locating the part that points to the old location and changing it appropriately. But that's a pain, and if you're doing this globally, the users don't have any choice over whether Java is in the path, even if they don't use it. So instead you might create a variable JAVA_PATH that points to the current SDK location. That way, it is easy to change, and individual users can choose whether or not to put %JAVA_PATH% in their own paths.
In Microsoft's case (the examples you noticed) the system root is never going to move, but by using a variable they could hard-code the default value of PATH rather than having to explicitly generate it during operating system installation.
PS: the environment variables referenced in PATH must all be system variables. Referencing a user variable will not work.
%VariableName% is the syntax for referencing an environment variable. The actual name is the part between the % symbols.
So your first line, when fully expanded, would evaluate to the value of the SystemRoot variable, followed by \system32;.
You'll need to use %...% if you want to make use of environment variables in the Windows shell, or if you want to define environment variables that reference other variables.
Is there a way to update a system's PATH variable through Ruby, permanently? I have the following:
envPath = ENV["PATH"].dup
if envPath.include? "C:\\oracle\\product\\11.2.0\\client_1\\bin;" then
envPath.slice! "C:\\oracle\\product\\11.2.0\\client_1\\bin;"
ENV["PATH"] = envPath
puts ENV["PATH"]
end
This successfully removes the variable I want to, but only for the current window - not permanently.
It's more a question about general computing and process behaviour not ruby special.
No this is not possible during runtime. Only a father process can configure the environment of it's child before start. Changing the environment of the father process or other processes during runtime isn't supported by any OS.
The documentation for the roo library says that in order to use Google spreadsheets I need to
set the environment variables ‘GOOGLE_MAIL’ and ‘GOOGLE_PASSWORD’ or
you pass the Google-name and -password to the Google#new method.
I'm new to Ruby, naively just tried to change the environment variable (on Windows) by doing this in the system properties, but it seems that it's not environment variables in this sense (and I guess that'd be a bad way to store sensitive data anyway)
I've deleted the environment variables from my (user not system) settings again, so back to square one. How do I follow this instruction? I don't understand what it means by "pass the Google-name and Google-password to the Google#new method", I'm trying to run the line
oo = Roo::Google.new('"'+sheetfull'"')
and I could ask for the details in the program rather than changing system settings (to make it easier for other people to use my code) with something along these lines
puts "What's your email?"
GOOGLE_MAIL = gets
puts "What's your password?"
GOOGLE_PASSWORD = gets
so that these 'environment variables' are set up before the spreadsheet is called with oo, or else it results in an error.
I'm not quite sure how I'd tell it that they've been given though... I tried the code above but it's obviously initialising GOOGLE_MAIL and GOOGLE_PASSWORD as constants(?) that don't get "passed to any methods"
Sorry if I've worded this poorly, I'm still learning all the lingo! Feel free to call me out on any of the things I've named etc. etc.
You can set environment variables using the instructions here: https://superuser.com/questions/284342/what-are-path-and-other-environment-variables-and-how-can-i-set-or-use-them
Alternatively, you can pass the values you prepared to roo like so:
Roo::Google.new(sheetfull, user: GOOGLE_MAIL, password: GOOGLE_PASSWORD)
I'm sometimes using some environment variables in my shell to pass some values to some shell or Ruby scripts. They use the value if the variable is set.
A few times I've noticed that some conditionals statements (based on the presence of such a variable) were executed even if I didn't set a value for the variable $DESTINATION. My scripts are exitting with an error and print the value. It's always something like /var/folders/9X/9XWGo2YVHP0iDllOTi886E+++TI/-Tmp-/[a file name]
As far as I can diagnose this, [a file name] is always something downloaded by something like Sparkle (the library that helps downloading and installing software updates in applications).
It's not that bad, but a little annoying that it is leaking in a completely different context than the one it's used in.
Anybody to confirm or deny my conclusions ?
I need to set the an environment variable from within Perl. Ideally, I need to query a variable and then change it if it is not what is required. Specifically it is the PATH variable I want to change.
How do I get and set these variables?
If you need to change environment variables globally and permanently, as if you set it in the control panel, then you have to muck with the registry (update: and now there are modules to do this, Win32::Env and Win32::Env::Path). Note that changing variables in the registry and "broadcasting" the change will not change the environment variables in some current processes, notably perl.exe and cmd.exe.
If you just want to change the current process (and subsequently spawned child processes), then the global %ENV hash variable is what you want (e.g. $ENV{PATH}). See perldoc perlvar.
$ENV{PATH}?
Keep in mind that environment variables only affect subprocesses, however. You can't run a Perl program, change %ENV, and then see that change in the parent process -- the environment does not work that way.
You can do that using the %ENV hash
$ENV{PATH} = 'C:\\Windows\;D:\\Programs';