こんばんは、saronpasuです。
今回は、RubyからWindowsの実行ファイル Exeを作ってみます。
RubyプログラムをExeファイルにすることで、Rubyがインストールされていない
他のWindowsマシンでも自分の作ったプログラムが実行できるようになります。
Exeファイルの生成だけならとても簡単です。
せっかくですから、実際にどうやってRubyプログラムを組むのかがわかるように、プロトタイプを作りながら説明して参ります。
まず、作りたいサンプルプログラムの内容です。
要件
・テキストファイルをパースして、特定の文字を含むかどうかを判定する
・ファイルは操作は、ドラック&ドロップで行う
・RubyがインストールされていないWindowsマシンで動作する
こんなものを作ってみます。
まずは、Rubyで動作するexample.rbというサンプルコードを構築してみましょう。
#!ruby
exit if ARGV.empty?
はい。
引数が空っぽの場合は終了する。という内容です。
ここにコードを足して行きます。
#!ruby
exit if ARGV.empty?
file_list = ARGV.find_all do |i|
File.exist?(i)
end
puts file_list
はい。
引数に渡されたファイルがちゃんと存在するかどうかを確認して、
存在するファイルのリストを生成します。
ちなみに、ARGVというのは、標準入力に渡された引数が入る配列のことを示します。
File.exist?というのは、ファイルの存在確認をするメソッドです。
$ ruby example.rb file_a.txt file_b.txt not_found.txt
-> file_a.txt
file_b.txt
試しに実行してみると、このような結果になります。
#!ruby
exit if ARGV.empty?
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
puts file_list
はい。
さきほどの処理にさらに条件を追加しました。
「1バイト以上のファイルが存在し、なおかつ読み取り可能であること」という条件です。
$ ruby example.rb file_a.txt zero_byte.txt not_found.txt it_is_directory
-> file_a.txt
このような結果になります。
#!ruby
exit if ARGV.empty?
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
pattern = /^.*(do).*(ru).*(by).*$/m
これから検索する正規表現パターンを生成しました。
テキストの中身に、「do」「ru」「by」という文字が、順番通りに含まれるかどうかを調べます。
正規表現オブジェクト『//』に、mオプションをつけることで、複数行にマッチングするようになります。
#!ruby
exit if ARGV.empty?
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
pattern = /^.*(do).*(ru).*(by).*$/m
match_list = file_list.find_all do |j|
open(j, 'r'){|k|
k.read.match(pattern)
}
end
puts match_list
はい。
ファイルリストをそれぞれ開いて、中身のテキストをパースして正規表現パターンにマッチするかどうかを調べています。
$ ruby example.rb match.txt unmatch.txt
-> match.txt
実行してみると、このような結果になります。
#!ruby
require 'win32ole'
exit if ARGV.empty?
wsh = WIN32OLE.new('WScript.Shell')
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
pattern = /^.*(do).*(ru).*(by).*$/m
match_list = file_list.find_all do |j|
open(j, 'r'){|k|
k.read.match(pattern)
}
end
wsh.popup('match!', 0, 'Do Ruby!') unless match_list.empty?
はい。
処理結果として、正規表現パターンにマッチする場合はポップアップメッセージを表示します。
今回は、ポップアップを表示するためにWin32OLEライブラリを使って、
Windows Scripting Host の、WScript.Shell オプジェクトを制御しました。
$ ruby example.rb match.txt

このような結果になります。
このままでは少々、不格好ですので整形します。
#!ruby -Ks
require 'kconv'
require 'win32ole'
exit if ARGV.empty?
def search(argument, pattern_string)
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
pattern = Regexp.new(pattern_string, Regexp::MULTILINE)
match_file = file_list.find_all do |filename|
open(filename, 'r'){|f|
f.read.match(pattern)
}
end
return match_file
end
def popup(message)
wsh = WIN32OLE.new('WScript.Shell')
wsh.popup(message, 0, 'Do Ruby!')
end
pattern = "^.*(Do|dO).*(Ru|rU).*(By|bY).*$"
unless search(ARGV, pattern,
popup('match!')
end
はい。
処理をメソッドに分けて、少しばかり正規表現パターンを変えました。
ついでに、マルチバイト対応もしてみましょう。
#!ruby
require 'win32ole'
exit if ARGV.empty?
def search(argument, pattern_string, 's')
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
pattern = Regexp.new(pattern_string, Regexp::MULTILINE)
match_file = file_list.find_all do |filename|
open(filename, 'r'){|f|
f.read.tosjis.match(pattern)
}
end
return match_file
end
def popup(message)
wsh = WIN32OLE.new('WScript.Shell')
wsh.popup(message, 0, 'Do Ruby!')
end
pattern = "^.*(Do|dO).*(Ru|rU).*(By|bY).*$"
unless search(ARGV, pattern,
popup('match!')
end
はい。これで、Windows環境とはことなる文字コードのテキストでも解析できるようになりました。
マルチバイト対応には、Kconvライブラリを使いました。
それでは、いよいよお待ちかねのExeを作成しましょう。
Exeの作成には、『Exerb』というソフトウェアを使用します。
Exerbをインストールした状態で、次のコマンドを実行します。
$ mkexy example.rb
これで、Exe作成用のレシピファイルが生成されました。
レシピファイルというのは、Exeの生成に必要な設定ファイルです。
作成されたレシピファイル
# Generated by mkexy
# on 2008-06-09 21:06
general:
startup: example.rb
core: cui
kcode: sjis
file:
example.rb:
win32ole.so:
file: c:/ruby/lib/ruby/1.8/i386-mswin32/win32ole.so
type: extension-library
nkf.so:
file: c:/ruby/lib/ruby/1.8/i386-mswin32/nkf.so
type: extension-library
kconv.rb:
file: c:/ruby/lib/ruby/1.8/kconv.rb
次に、このレシピファイルを開いてファイルの最後に4行だけ追記しましょう。
stringio.so:
file: C:/ruby/lib/ruby/1.8/i386-mswin32/stringio.so
type: extension-library
※最後の改行を含めて、4行です。
Exeファイルの作成
ここまでできたら、あとは仕上げです。
$ exerb example.exy
このように、作成したレシピファイルを渡してあげると example.exe というExeファイルが作成されます。
あとは、試しに「 do hoge ru fuga by 」と書いたテキストを作って、
example.exeアイコンへドラッグ&ドロップしてみましょう。

ちゃんと、「match!」とポップアップがでるはずです。
このプログラムの作成には、Ruby環境が必要ですが
作成したExeはRubyがインストールされていないマシンでも 実行できます。
#!ruby
require 'win32ole'
exit if ARGV.empty?
def search(argument, pattern_string, 's')
file_list = ARGV.find_all do |i|
File.exist?(i) && File.file?(i) && File.readable?(i) && File.size?(i)
end
pattern = Regexp.new(pattern_string, Regexp::MULTILINE)
match_file = file_list.find_all do |filename|
open(filename, 'r'){|f|
f.read.tosjis.match(pattern)
}
end
return match_file
end
def popup(message)
wsh = WIN32OLE.new('WScript.Shell')
wsh.popup(message, 0, 'Do Ruby!')
end
pattern = "^.*(ぬ|ヌ).*(る|ル).*(ぽ|ポ).*$"
unless search(ARGV, pattern,
popup('ガッ!')
end

なんていうこともできますね。