Win32OLEをつかってWindowsのサービスをリモートから起動停止してみる
Win32OLEがすごく面白かったのでWindowsのサービスをリモートから起動停止するコードを書いてみました。
Win32OLEを使ったrubyのコード
require 'win32ole' すれば後はvbsで書くのとあまりかわりはありません。vbsと違い強力なrubyのHashやArrayやイテレータで遊べます。
locator = WIN32OLE.new( "WbemScripting.SWbemLocator" ) service = locator.ConnectServer(hostname ,"root/cimv2", account, password) service.InstancesOf("Win32_Service").each {|v| p v.class: p v }
使い方
ruby foo.rb -h hostname -a accout -p password -c {stop|start}
下のほうにある svcList に起動/停止したいサービスを書いて実行してください。
#!/usr/bin/ruby require 'win32ole' require 'optparse' require 'socket' opt = OptionParser.new o = {} def usage puts puts " usage: #{__FILE__} -h hostname -a accout -p password -c {stop|start}" puts " -h hostname" puts " -a accout" puts " -p password" puts " -c {stop|start}" exit end begin opt.on('-h [hostname]') {|v| o[:hostname] = v } opt.on('-a [account]') {|v| o[:account] = v } opt.on('-p [password]') {|v| o[:password] = v } opt.on('-c [ctl]') {|v| o[:service_ctl] = v } opt.on("--help") {|v| o[:help] = v} opt.parse!(ARGV) rescue puts "#{__FILE__}: unrecognized option" usage end # usage ... usage if o.size == 0 usage if o[:help] usage unless o[:service_ctl] == "stop" || o[:service_ctl] == "start" class ServiceCtl def initialize() @h = Hash.new{|h,k| h[k]=[]} @table ={} end def getdata(service) service.InstancesOf("Win32_Service").each {|v| @h[v.name] = v } @h end def start(service,svcList) @table = getdata(service) svcList[:start].each {|s| if @table.key?(s) == true r = @table[s].StartService puts statusmsg(r, s, :ctl => 0) end } end def stop(service,svcList) @table = getdata(service) svcList[:stop].each {|s| if @table.key?(s) == true r = @table[s].StopService puts statusmsg(r, s, :ctl => 1) end } end def statusmsg(r, s, opt ={}) opt[:ctl] == 0 ? msg = "startng a service" : msg = "stopping a service" case r when 0 "#{msg} (#{s}) - status:(success)" when 5 "#{msg} (#{s}) - status:(stopped)" when 8 "#{msg} (#{s}) - status:(abort)" when 10 "#{msg} (#{s}) - status:(running)" else "#{msg} (#{s}) - status:(illegal)" end end end # main svcList = { :stop => ["wuauserv" ,"Themes" ,"WebClient"], :start => ["wuauserv", "Themes", "WebClient"] } locator = WIN32OLE.new( "WbemScripting.SWbemLocator" ) if Socket.gethostname == o[:hostname] || 'localhost' == o[:hostname] service = locator.ConnectServer() else service = locator.ConnectServer( o[:hostname] ,"root/cimv2", o[:account], o[:password] ) end so = ServiceCtl.new case o[:service_ctl] when "stop" so.stop(service,svcList) when "start" so.start(service,svcList) else usage end
参考
Microsoft の Hey, Scripting Guy! にvbsやwshやwmiのサンプルがたくさんあるので参考になります。また WMI Administrative Tools(CIM Studio) を使うとオブジェクトツリーを参照できてとても便利です。
- Hey, Scripting Guy!
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/default.mspx
- WMI Administrative Tools