通过Ruby保持环境变量

时间:2021-11-07 11:06:51

I am trying to set my DOS environment variable in Ruby, and have it persist after the script exits. For example, if I want a ruby script set_abc_env.rb to set environment variable 'ABC' to 'blah', I expect to run the following:

我试图在Ruby中设置我的DOS环境变量,并在脚本退出后保持它。例如,如果我想要一个ruby脚本set_abc_env.rb将环境变量'ABC'设置为'blah',我希望运行以下命令:

C:> echo %ABC%
C:> set_abc_env.rb
C:> echo %ABC% blah

How do I do this?

我该怎么做呢?

2 个解决方案

#1


25  

You can access environment variables via Ruby ENV object:

您可以通过Ruby ENV对象访问环境变量:

i = ENV['ABC']; # nil
ENV['ABC'] = '123';
i = ENV['ABC']; # '123'

Bad news is, as MSDN says, a process can never directly change the environment variables of another process that is not a child of that process. So when script exits, you lose all changes it did.

坏消息是,正如MSDN所说,一个过程永远不能直接改变另一个不属于该过程子进程的进程的环境变量。因此,当脚本退出时,您将丢失它所做的所有更改。

Good news is what Microsoft Windows stores environment variables in the registry and it's possible to propagate environment variables to the system. This is a way to modify user environment variables:

好消息是Microsoft Windows在注册表中存储环境变量,并且可以将环境变量传播到系统。这是一种修改用户环境变量的方法:

require 'win32/registry.rb'

Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
  reg['ABC'] = '123'
end

The documentation also says you should log off and log back on or broadcast a WM_SETTINGCHANGE message to make changes seen to applications. This is how broadcasting can be done in Ruby:

该文档还说明您应该注销并重新登录或广播WM_SETTINGCHANGE消息,以便对应用程序进行更改。这就是如何在Ruby中完成广播:

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)  

#2


1  

For anyone else looking for a solution for this and looking for a more of a hack that doesn't require logging in or out I came up with this solution for a similar problem :

对于其他寻找解决方案并寻找更多不需要登录或退出的黑客的人,我想出了一个类似问题的解决方案:

WORKAROUND:

解决方法:

My work around is dependent on combination of ruby and a command line utility called SETENV.EXE develped by Vincent Fatica. It's more than a decade old at this point but works fine in windows XP ( didn't test under Windows 7 yet). It works better than setx utility available from MS IMHO. At lest for deleting stuff. Make sure setenv is available from command line. Put it in some c:\tools and put c:\tools in your PATH.

我的工作依赖于ruby和一个名为SETENV.EXE的命令行实用程序的组合,该实用程序由Vincent Fatica开发。它已经超过十年了,但在Windows XP中运行良好(尚未在Windows 7下测试)。它比MS恕我直言的setx实用工具更好。至少删除东西。确保从命令行可以使用setenv。将它放在一些c:\ tools中,并将c:\ tools放在PATH中。

Here is a short example of a method using it:

以下是使用它的方法的简短示例:

def switch_ruby_env
  if RUBY_VERSION.match("1.8.7").nil?  
    `setenv -m CUSTOM_PATH " "`
  else
    `setenv -m CUSTOM_PATH -delete`
  end
end 

#1


25  

You can access environment variables via Ruby ENV object:

您可以通过Ruby ENV对象访问环境变量:

i = ENV['ABC']; # nil
ENV['ABC'] = '123';
i = ENV['ABC']; # '123'

Bad news is, as MSDN says, a process can never directly change the environment variables of another process that is not a child of that process. So when script exits, you lose all changes it did.

坏消息是,正如MSDN所说,一个过程永远不能直接改变另一个不属于该过程子进程的进程的环境变量。因此,当脚本退出时,您将丢失它所做的所有更改。

Good news is what Microsoft Windows stores environment variables in the registry and it's possible to propagate environment variables to the system. This is a way to modify user environment variables:

好消息是Microsoft Windows在注册表中存储环境变量,并且可以将环境变量传播到系统。这是一种修改用户环境变量的方法:

require 'win32/registry.rb'

Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
  reg['ABC'] = '123'
end

The documentation also says you should log off and log back on or broadcast a WM_SETTINGCHANGE message to make changes seen to applications. This is how broadcasting can be done in Ruby:

该文档还说明您应该注销并重新登录或广播WM_SETTINGCHANGE消息,以便对应用程序进行更改。这就是如何在Ruby中完成广播:

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)  

#2


1  

For anyone else looking for a solution for this and looking for a more of a hack that doesn't require logging in or out I came up with this solution for a similar problem :

对于其他寻找解决方案并寻找更多不需要登录或退出的黑客的人,我想出了一个类似问题的解决方案:

WORKAROUND:

解决方法:

My work around is dependent on combination of ruby and a command line utility called SETENV.EXE develped by Vincent Fatica. It's more than a decade old at this point but works fine in windows XP ( didn't test under Windows 7 yet). It works better than setx utility available from MS IMHO. At lest for deleting stuff. Make sure setenv is available from command line. Put it in some c:\tools and put c:\tools in your PATH.

我的工作依赖于ruby和一个名为SETENV.EXE的命令行实用程序的组合,该实用程序由Vincent Fatica开发。它已经超过十年了,但在Windows XP中运行良好(尚未在Windows 7下测试)。它比MS恕我直言的setx实用工具更好。至少删除东西。确保从命令行可以使用setenv。将它放在一些c:\ tools中,并将c:\ tools放在PATH中。

Here is a short example of a method using it:

以下是使用它的方法的简短示例:

def switch_ruby_env
  if RUBY_VERSION.match("1.8.7").nil?  
    `setenv -m CUSTOM_PATH " "`
  else
    `setenv -m CUSTOM_PATH -delete`
  end
end