我正在尝试在 Ruby 中设置我的 DOS 环境变量,并在脚本退出后让它保持不变。例如,如果我想要一个 ruby 脚本set_abc_env.rb
将环境变量 'ABC' 设置为 'blah',我希望运行以下命令:
C:> echo %ABC%
C:> set_abc_env.rb
C:> echo %ABC% blah
我该怎么做呢?
我正在尝试在 Ruby 中设置我的 DOS 环境变量,并在脚本退出后让它保持不变。例如,如果我想要一个 ruby 脚本set_abc_env.rb
将环境变量 'ABC' 设置为 'blah',我希望运行以下命令:
C:> echo %ABC%
C:> set_abc_env.rb
C:> echo %ABC% blah
我该怎么做呢?
您可以通过 Ruby ENV 对象访问环境变量:
i = ENV['ABC']; # nil
ENV['ABC'] = '123';
i = ENV['ABC']; # '123'
坏消息是,正如 MSDN所说,一个进程永远不能直接更改不是该进程子进程的另一个进程的环境变量。因此,当脚本退出时,您会丢失它所做的所有更改。
好消息是 Microsoft Windows 将环境变量存储在注册表中,并且可以将环境变量传播到系统。这是一种修改用户环境变量的方法:
require 'win32/registry.rb'
Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
reg['ABC'] = '123'
end
该文档还说您应该注销并重新登录或广播 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)
对于其他正在为此寻找解决方案并寻找更多不需要登录或退出的黑客的人来说,我想出了针对类似问题的解决方案:
解决方法:
我的工作依赖于 ruby 和由 Vincent Fatica 开发的名为SETENV.EXE的命令行实用程序的组合。此时它已有十多年的历史,但在 Windows XP 中运行良好(尚未在 Windows 7 下测试)。它比 MS 恕我直言的 setx 实用程序更好。至少是为了删除东西。确保 setenv 在命令行中可用。把它放在一些 c:\tools 中,然后把 c:\tools 放在你的 PATH 中。
这是使用它的方法的简短示例:
def switch_ruby_env
if RUBY_VERSION.match("1.8.7").nil?
`setenv -m CUSTOM_PATH " "`
else
`setenv -m CUSTOM_PATH -delete`
end
end