Ruby: Can I update the system environment variables? - ruby

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.

Related

% in Windows environmental variables value

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.

Strange env variables in Mac OS X

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 ?

Running another ruby script with globals intact?

For reasons that are a little hard to explain, I need to do the following: I have a master.rb file that sets some global like: a = 1. I want to call another file other_file.rb that will run with the globals that were set in the master file. In python I'd use runpy.run_module( 'other_module', globals() ).
Can anyone think of an equivalent in Ruby? I've looked at require, include, and load, but none seem to do quite what I need, specifically they don't pull the globals into the other_file.rb. Note that I am not trying to fork a new process, just hand execution over to "other_module" while maintaining the state of the globals.
a=1 is not a global variable, it is a local variable that gets scoped to the file. If you really nee this behavior, use $a=1 to set global variables.
If you absolutely must, you can use globals, and they're declared with the $ prefix. They are highly discouraged because there is only one global namespace, which makes collisions possible. Generally they are used for interpreter configuration, like $LOAD_PATH.
A better approach is to use a module that has instance variables:
module MyContainer
def self.settings
#settings ||= { }
end
end
MyContainer.settings[:foo] = :bar
This has the advantage of keeping your variables contained in a namespace while not preventing other sub-programs from accessing them.
Keep in mind this will only work within the context of the same Ruby process or children created using fork, so using system or exec will not work. Remember also that forked processes need to use IPC to communicate with their parent.

Use Ruby to permanently (ie, in the registry) set environment variables?

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.

How can I set the Windows PATH variable from Perl?

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';

Resources