LoginSignup
1
1

More than 5 years have passed since last update.

ruby+ocra 1.3.5+特殊な環境でexe化に失敗する件

Last updated at Posted at 2015-05-22

特殊な環境において

ocraでrubyスクリプトをexe化しようとすると
downcaseがどうこう言われてexe化に失敗する事があります。

原因は

ロード済みDLLの探索時にGetModuleFileNameが呼ばれるが、
マルチバイト文字列を適切にエンコードしないままになっているため
- アンチウィルス/パーソナルファイアウォールソフトが日本語ディレクトリ名に格納されてる
- ruby自体が日本語ディレクトリに格納されてる

などのケースに置いて失敗します。
後者はともかく、前者を対策するのは面倒くさい為ちゃっちゃとパッチ書いちゃう

patch.diff
diff U3Bb C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/ocra-1.3.5/bin/old-ocra C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/ocra-1.3.5/bin/ocra
--- C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/ocra-1.3.5/bin/old-ocra  Fri May 22 18:24:56 2015
+++ C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/ocra-1.3.5/bin/ocra  Fri May 22 18:38:21 2015
@@ -952,7 +952,7 @@
       require 'Win32API'

       enumprocessmodules = Win32API.new('psapi', 'EnumProcessModules', ['L','P','L','P'], 'L')
-      getmodulefilename = Win32API.new('kernel32', 'GetModuleFileName', ['L','P','L'], 'L')
+      getmodulefilename = Win32API.new('kernel32', 'GetModuleFileNameW', ['L','P','L'], 'L')
       getcurrentprocess = Win32API.new('kernel32', 'GetCurrentProcess', [], 'L')

       bytes_needed = 4 * 32
@@ -968,9 +968,9 @@

       handles = module_handle_buffer.unpack("I*")
       handles.select { |handle| handle > 0 }.map do |handle|
-        str = "\x00" * 256
-        modulefilename_length = getmodulefilename.call(handle, str, str.size)
-        Ocra.Pathname(str[0,modulefilename_length])
+        str = "\x00\x0" * 256
+        modulefilename_length = getmodulefilename.call(handle, str, str.size / 2)
+        Ocra.Pathname(str[0,modulefilename_length*2].force_encoding("utf-16le").encode "utf-8")
       end
     end

マルチバイト環境固有の問題は英語圏に説明するのは難しいし、いい感じのテストケース用意するのが難しすぎる

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1