8

I need to run a ruby script in elevated mode (Admin priviledges) under Windows. Is it possible?

Ricardo Acras
  • 35,784
  • 16
  • 71
  • 112
  • 2
    Open a terminal (cmd.exe) with Admin privileges and run ruby from there? – Casper Nov 25 '11 at 11:20
  • Yes, that´s a way to elevate anything isn´t it? I need a way that my script ruby elevates itself. Obviously windows will ask for admin password, that´s ok for me. – Ricardo Acras Nov 25 '11 at 18:47

4 Answers4

11

Here's how to do it. The easiest way is to restart your executable with elevaded (Admin) privileges using ShellExecute.

With Ruby you do it like this:

require 'win32ole'

shell = WIN32OLE.new('Shell.Application')
shell.ShellExecute('path_to_ruby_program', nil, nil, 'runas')

If you have Windows UAC enabled this will give you the familiar Windows pop up dialog that requests Admin privileges. Once you click Yes, your process will run with Admin rights.

The secret trick here is using the the undocumented ShellExecute operation parameter runas, which will elevate the requested operation.

http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx

Also related discussion on how to manually create an elevated command prompt shortcut (which might be a good enough solution in some cases):

http://www.sevenforums.com/tutorials/3718-elevated-command-prompt-shortcut.html

Casper
  • 33,403
  • 4
  • 84
  • 79
2

I would like to thank Casper and thegreendroid for this modified solution.

I couldn't get their examples to run as is so with a touch more research I put this together. I did a bit of a search for execute_command, as my installation of ruby 1.9.3 didn't know what to do with it, and I couldn't find anything so I used backticks. The \ had to be escaped. The 2>&1 bit is so ruby actually gets the output instead of a blank string, and if that output matches the Regexp /ERROR/ then you don't have admin privileges, so we want it to return nil.

This will relaunch itself with administrative privileges then load whatever you put in the require with the comment after it.

require 'win32ole'
def running_in_admin_mode?
    (`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil? 
end

if running_in_admin_mode?
    require './main.rb' # load the actual program here.
else
    path = 'rubyw.exe ' + File.expand_path(__FILE__) # optionally 'ruby.exe '
    shell = WIN32OLE.new('Shell.Application')
    shell.ShellExecute(path, nil, nil, 'runas')
end

You could drop the def block and change the if statement to

if (`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil?

for the sake of brevity. Also you could lose the shell variable:

WIN32OLE.new('Shell.Application').ShellExecute(path, nil, nil, 'runas')

Possible Gotcha: This could infinite loop if running_in_admin_mode? fails repeatedly, but it worked perfectly for me.

  • 1
    `ShellExecute` syntax should be: `shell.ShellExecute("rubyw.exe", path, "", 'runas')` more info can be found here: http://rubyonwindows.blogspot.com.es/2007/05/launching-apps-and-printing-docs-with.html – Lluís Nov 21 '13 at 10:21
2

Thanks to other authors, I've come to work with this (tested on windows 8):

Add this at the top of a ruby script:

def running_in_admin_mode?
  (`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil? 
end

unless running_in_admin_mode?
  require 'win32ole'
  shell = WIN32OLE.new('Shell.Application')
  shell.ShellExecute("ruby", File.expand_path(__FILE__), nil, 'runas')
  exit
end

# admin rights ensured
do_something()

Or you could just have a launcher.cmd containing

cd full\path
ruby myscript.rb

and launch this cmd file with admin rights

Once you've tested with ruby you can try rubyw

Rivenfall
  • 1,189
  • 10
  • 15
1

Another method is to ensure you do not run your script in non-admin mode. I have found this solution to be satisfactory in my experience.

It can be determined whether a script is running in admin mode like so -

def running_in_admin_mode?
  query_admin_mode_cmd = 'reg query "HKU\S-1-5-19"'
  output, exit_status = execute_command(query_admin_mode_cmd)
  exit_status == 0
end

Credit goes to Peter McEvoy for his answer here

Community
  • 1
  • 1
thegreendroid
  • 3,239
  • 6
  • 31
  • 40