In my line of work I end up trying to move a large amount of text from web pages into things like Word and Excel. Getting the Text from the Web Browser is easy…Putting the text with formatting into an Office app could be a lot of work trying to parse through all the HTML and send the equivalent formatting commands with the text. Fortunately, Word and Excel had the ability to paste from the clipboard HTML and render it with the correct formatting! …Only problem is that for some reason, no one added HTML support in the Win32::Clipboard gem?!? (At least not in the 1.8.x version of Ruby, which I use.) So I spent a few hours looking over the existing clipboard.rb file, found a VBA example of an HTML Copy, and came up with the following code: Continue reading »
If you try to “compile” a Ruby script that has the Watir gem in it with OCRA, you will find that running the compiled .exe file on a computer without the Watir gem previously being installed may result in this error:
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `initialize': unknown OLE server: `AutoItX3.Control' (WIN32OLERuntimeError)
HRESULT error code:0x800401f3
Invalid class string from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `new'
from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `autoit'
from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:425:in `autoit'
from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:422:in `set_window_state'
from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:398:in `maximize'
...
Huh? Why am I getting a WIN32OLE error? This all runs fine on my computer when I tested it! … Well, it seems that Watir uses its own version of a win32ole gem, and not the one that you already have installed. In fact, when you compile a Ruby script that has both win32ole and watir gems, you will need to comment out the “require ‘win32ole’” line in order for it to work. Anyway… as part of the win32ole gem install, it seems that it registers the AutoItX3.dll file into the registry. OCRA will, however, *NOT* copy this file over and register it for you, so you may see the error above.
So…the trick is add the AutoItX3.dll file to your OCRA compile, and to temporarily register the DLL before calling watir or win32ole commands. I simply copied the DLL from the win32ole gem directory to my Ruby script’s working directory, and then added it to my OCRA compile command:
C:\Server4\Dev\MyProg>ocra --console --icon c:/Server4/Dev/icons/exonets.ico myprog.rb AutoItX3.dll
OCRA will add the DLL to the EXE and when run will place it in the current temporary directory. After that you need to run the DLL register command to make it an OLE server, then when done, be sure to unregister it before your program completes.
Here a sample of code that I use to accomplish all this: Continue reading »
My friendly oil change person taught me the trick to resetting my oil change light on my 2007 Saturn VUE:
When you turn the car back on, the Oil Change light will stop coming on.
While doing a quick search for Ruby code that could catch and print out the Beacon packet that Tivo machines send out on the local network, I was shocked to not find anything….tons of stuff in Perl….but nothing Ruby! Unbelievable! So I went and figured out what the code would be in Ruby. Here’s what I got:
require 'socket'
require 'exo/xdump'
trap("INT") do
puts "---[Ctrl-C: Exiting]---\n\n"
Kernel.exit(0)
end
BasicSocket.do_not_reverse_lookup = true
s = UDPSocket.new
s.bind("0.0.0.0", 2190)
loop do
flg = IO.select([s], nil, nil, 5)
if flg
text, sender = s.recvfrom_nonblock(1024)
puts "[#{Time.now}] #{sender[3]} sent beacon packet:"
puts "[#{Time.now}]\n#{text.hexdump}"
end
end
Nothing too fancy. The beacon is sent out as a UDP packet to port 2190. The code looks for data on the socket, then retrieves the the data and prints it out in a hex dump format like so:
[Sun Mar 07 20:37:53 -0800 2010] 10.11.12.52 sent beacon packet: [Sun Mar 07 20:37:53 -0800 2010] 000000: 7469 766f 636f 6e6e 6563 743d 310a 7377 |tivoconnect=1.sw| 000010: 7665 7273 696f 6e3d 392e 332e 3262 2d30 |version=9.3.2b-0| 000020: 312d 322d 3134 300a 6d65 7468 6f64 3d62 |1-2-140.method=b| 000030: 726f 6164 6361 7374 0a69 6465 6e74 6974 |roadcast.identit| 000040: 793d 3234 3030 3030 30Xx XxXx XxXx XxXx |y=2400000XXXXXXX| 000050: Xx0a 6d61 6368 696e 653d XxXx XxXx XxXx |X.machine=XXXXXX| 000060: 0a70 6c61 7466 6f72 6d3d 7463 642f 5365 |.platform=tcd/Se| 000070: 7269 6573 320a 7365 7276 6963 6573 3d54 |ries2.services=T| 000080: 6956 6f4d 6564 6961 5365 7276 6572 3a38 |iVoMediaServer:8| 000090: 302f 6874 7470 0000 0000 0000 0000 0000 |0/http. |
The identity and the machine values have been changed just to be safe
A big issue that a lot of folks have with UDP sockets in Ruby is trying to get a non-blocking read working correctly. The use of the IO.select above seems to be the best answer that I’ve seen…but its still not perfect. Some folks have been trying out eventmachine (See the “Non-Blocking UDP” thread over on Ruby Forum), but for this simple test, the IO.select should work just fine.
I covered the hexdump function in a previous post.
Ever wanted to have a spell check function in your Ruby Program? As long as you have MS Word installed, you can use the Spellcheck function from your program. Here’s the code:
require 'exo/iswindows'
if not RUBY_PLATFORM.isWindows?
puts "This program only runs under Windows!"
exit
end
require 'win32ole'
def spellcheck(scstring)
word = WIN32OLE.new('Word.Application')
doc = word.Documents.Add ## Blank document
word.Selection.Text = scstring
word.Dialogs(828).Show
### return the corrected text
if not scstring[/ /] ## only one word with no spaces in the string
# highlight the word first,
word.Selection.MoveLeft( 'Unit'=>2,
'Count'=> 1,
'Extend'=>2)
end
## multiple words end up already selected after the spell check
# then retrieve.
correct = word.Selection.Text
doc.close(0)
word.Quit
return correct
end
if __FILE__ == $0
puts "Corrected => #{spellcheck(ARGV[0])}"
end
The program opens a new document, pastes the text to check into the document, and then brings up the spellcheck dialog box with any words it can’t find in the dictionary and prompts you to correct the mistakes. Here’s an sample output:
C:\Server6\Dev\Ruby>ruby spellcheck.rb "this is a test srting to seee how the slpell check is working" Corrected => This is a test string to see how the spell check is working C:\Server6\Dev\Ruby>ruby spellcheck.rb antidisestablishmenttarianism Corrected => antidisestablishmentarianism
For some reason, if you check multiple words, the dialog auto-closes after the last ‘fix’ …but if its just one word, it stays open until you click the close button. Conversely, multiple words stay selected in the Word doc after the dialog closes, but with only one word, it does not stay selected, and you have to select it back in order to read it off the page of the document.
First off, let me say that there is not an original thought in any of this code, since it has all been taken from a number of different articles out on the Internet. The Daemonizing code was taken from the Active State Code Recipes area.
One of my customers has a number of database servers that we would like to monitor and see what the state of the clusters are. The problem is that the clustat command — that used to be run-able by everyone in a lesser version of RHEL — is now only usable by root in RHEL v5.3!. Not wanting to give out root access to everyone, we decided that a quick little custom server that provided the output of the clustat command in XML format would do the trick. Then I just wrote a Ruby program to query all the Clustat XML servers and display the results in a readable format. If there is enough interest, I can post a public version of that program.
Here’s the code: Continue reading »
When I want to distribute a Ruby script to a customer, sometimes its just easier to use something like Ocra to package up all the files needed into one nice .exe file that I can send over. Since I use Rake a lot, I wanted to figure out a way to automate the process. Here’s a simple example:
...
desc "List available Tasks"
task :default do
sh %{ rake -T }
end
desc "Make BI_Competition_Status_Report.exe file"
task :exe do
sh %{ cd lib && rake exe }
sh %{ move lib\\BI_Competition_Status_Report.exe .}
end
...
This is in your main project Rakefile. Since I’m using NetBeans, it places my Ruby files in a ./lib directory. The first sh command simply CD’s down to lib, and runs a second Rakefile located there:
desc "Make BI_Competition_Status_Report.exe file"
task :exe do
sh %{ ocra --windows --icon C:/Server12/Dev/Ruby/Exonets.ico BI_Competition_Status_Report.rb}
end
This is the actual Ocra command that packages up the Ruby app into a single .exe file. When this rake command ends, the last command in the previous Rakefile moves the completed .exe file up to the current directory.
Anyone who has ever worked with networks at one point or another always ends up running a telnet or ping command over and over again to generate traffic and check if one computer can talk to another. After running that command a couple dozen times, one starts to think that maybe it would be better to write a program to do this instead.
One of my customers has a number of RedHat servers that I’m not allowed to install any programing language like Ruby or Perl on that I would normally use to write such a program…however, they have a complete Python installation for some reason. Not to argue with fate, I wrote the following script to run my tests with:
#
# nettest.py
#
import sys
import socket
import time
host = sys.argv[1]
port = int(sys.argv[2])
# type => ["tcp" or "udp"]
type = sys.argv[3]
test = ""
if len(sys.argv) > 4 :
test = sys.argv[4]
while 1 :
if type == "udp":
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
else:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
try:
if type == "udp":
s.sendto("--TEST LINE--", (host, port))
recv, svr = s.recvfrom(255)
s.shutdown(2)
print "Success connecting to " + host + " on UDP port: " + str(port)
else:
s.connect((host, port))
s.shutdown(2)
print "Success connecting to " + host + " on TCP port: " + str(port)
except Exception, e:
try:
errno, errtxt = e
except ValueError:
print "Cannot connect to " + host + " on port: " + str(port)
else:
if errno == 107:
print "Success connecting to " + host + " on UDP port: " + str(port)
else:
print "Cannot connect to " + host + " on port: " + str(port)
print e
if test != "C" :
sys.exit(0)
s.close
time.sleep(1)
This is run like so: Continue reading »
I found it a bit odd that there doesn’t seem to be any tutorials on how to automate Microsoft Visio using Ruby. Most of the other Office apps have a bunch of pages on automation, but none on Visio….that or my Google Fu is leaving me
So…. Here’s a brief tutorial on how to automate Visio using Ruby. First thing you need to do is bring in the WIN32OLE module and create a new instance of the Visio application
require 'win32ole'
visio = WIN32OLE.new('Visio.Application')
If you already have Visio running, you can connect to it with this line instead
visio = WIN32OLE.connect('Visio.Application')
Once you have your instance, its usually best to load in all the constants from the application. Visio has tons and tons, so if you are going to try and convert any VBA or C++ code over, you will need these.
class VisioConst # Empty class to hold constants end ... WIN32OLE.const_load(visio, VisioConst)
Be sure to put the class declaration below the ‘require’ statements so your code will read better. Now we will load in a Visio template just to make things easier on us. Continue reading »
I’ve been working with Visio lately and noticed that when my programs start it up, Visio was not coming up maximized. Since I wanted to be able to see my work full screen, I started looking for a way to force it to maximized mode. I quickly learned that there is no convenient ‘visio.Maximize’ method to use. Bummer. Other Office apps have a ‘.WindowState’ parameter that can be set to minimize, maxamize, restore, or hide the application window, but not Visio. Guess that would make it too easy
For Visio, you can use the ‘ShowWindow’ function from the user32.dll to do the work:
require 'Win32API'
##Possible cmd values:
# Hidden => 0
# Restored => 1
# Minimized => 2
# Maximized => 3
def ShowWindow(wndHandle, cmd)
wndShowWindow = Win32API.new("user32", "ShowWindow", ["p","i"], "i")
wndShowWindow.call(wndHandle, cmd)
end
‘wndHandle‘ is the infamous Window Handle used in the lower-level Windows APIs. At least Visio has a way to return the handle. So in your program:
Continue reading »






