From: Jos Backus Date: 2004-05-08T03:28:59+09:00 Subject: Ruby Installer for Windows: use of Win32OLE bug causes crash This is with the latest Ruby Installer for Windows, 181-13-rc2. When I run the script below I see: C:\localbin>diskspace.rb (offline mode: enter name=value pairs on standard input) ^Z (eval):1214: [BUG] Segmentation fault ruby 1.8.1 (2003-12-25) [i386-mswin32] This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. C:\localbin> When I replace the get_diskinfo call with a call to fake_get_diskinfo, skipping the Win32OLE calls, the program works fine (but is useless, of course). I have added a comment to (closed) bug 522 on RubyForge. Any help is appreciated. #!ruby require 'win32ole' require 'cgi' require 'stringio' outputfilename = "diskspace.htm" hosts = [] File.open("diskspace_hosts.txt").each_line do |line| next if line =~ /^\s*(#|$)/ hosts << line.chomp end hosts =%w(localhost localhost localhost somehost) class DiskInfo attr_reader :deviceid, :size, :freespace def initialize(deviceid, size, freespace) @deviceid, @size, @freespace = deviceid, size.to_i, freespace.to_i end def pct_free freespace.to_f / size * 100 end end def fake_get_diskinfo(host) result = [] result << DiskInfo.new('C:', 10000000000, 5000000000) result << DiskInfo.new('D:', 20000000000, 8000000000) end # Returns a list of DiskInfo objects for host, or nil def get_diskinfo(host) result = [] begin wmi = WIN32OLE.connect("winmgmts://#{host}/root/cimv2") rescue return nil end disks = wmi.ExecQuery("Select * from Win32_LogicalDisk") disks.each do |disk| next if disk.Size.nil? result << DiskInfo.new(disk.DeviceID, disk.Size, disk.FreeSpace) end result end # Map freespace percentage to color codes def alert_color(value) case value when 20..100; "lightgreen" when 10...20; "yellow" when 5...10; "orange" when 0...5; "red" else raise # Shouldn't happen end end diskdata = hosts.collect do |host| [ host, get_diskinfo(host) ] end File.open(outputfilename, "w") do |file| # Hack alert: # Since cgi.out writes to $DEFAULT_OUTPUT we capture the output in outstring by directing $DEFAULT_OUTPUT to it. # We need to do this because we want to strip the first 3 lines from the output (the HTTP header). outstring = StringIO.new $DEFAULT_OUTPUT = outstring cgi = CGI.new("html4") # add HTML generation methods cgi.out { cgi.html { cgi.head { "\n" + cgi.title{"Disk Space Overview"} } + cgi.body { "\n" + cgi.h2 { "Disk space by host by drive" } + cgi.p { "Last updated: " + Time.now.to_s } + cgi.table { cgi.tr { cgi.th({"width" => "120%", "align" => "left"}) { "Host" } + cgi.th { "Disk" } + cgi.th { "Total" } + cgi.th { "Free" } + cgi.th { "%" } } + diskdata.collect do |host, di| unless di cgi.tr { cgi.td("bgcolor" => "red") { host } } else di.collect { |disk| cgi.tr { cgi.td { host } + cgi.td { disk.deviceid } + cgi.td { disk.size / 1024 ** 3 } + cgi.td { disk.freespace / 1024 ** 3 } + cgi.td("bgcolor" => alert_color(disk.pct_free)) { "%3.2d" % disk.pct_free } } } end end.join("\n") } } } } outstring.rewind file.puts outstring.readlines[3..-1] # Drop HTTP header outstring.close end exit -- Jos Backus _/ _/_/_/ Sunnyvale, CA _/ _/ _/ _/ _/_/_/ _/ _/ _/ _/ jos at catnook.com _/_/ _/_/_/ require 'std/disclaimer'