From: Masahiro Kitajima Date: 2004-06-16T16:10:07+09:00 Subject: [ruby-dev:23693] Shell.Application on WIN32OLE かとんぼです。  WIN32OLE を使ったスクリプトで、[BUG] で落ちるケースを見つけまし た。 #! ruby -Ks require "win32ole" shell = WIN32OLE.new("Shell.Application") mycom = shell.NameSpace(17).Items # マイコンピュータ p mycom.Item(1).Verbs.Item(0).Name gets GC.start # ここで落ちる。 gets #=> "開く(&O)" t.rb:7: [BUG] Segmentation fault ruby 1.8.2 (2004-05-27) [i386-mswin32]  これを私の日記に書いていたのですが、Yamamoto さんより回避策のツッ コミをいただきました。私はこういったところまでコードを読めてなく て、どうしたものかわかりません。勿体無いので Yamamoto さんの同意 を得て以下に引用します。 Yamamoto さん wrote: > ・Yamamoto (2004/06/13 21:58) > このパッチで落ちなくなります。 > Index: win32ole.c =================================================================== RCS file: /var/cvs/src/ruby/ext/win32ole/win32ole.c,v retrieving revision 1.22 diff -u -w -b -p -r1.22 win32ole.c --- win32ole.c 8 May 2004 03:54:51 -0000 1.22 +++ win32ole.c 13 Jun 2004 07:36:00 -0000 @@ -67,7 +67,6 @@ (x) = 0;\ }\ }\ - CoFreeUnusedLibraries();\ } #define OLEData_Get_Struct(obj, pole) {\ > FolderItemVerbs#Release() と FolderItemVerb#Release() > の間に CoFreeUnusedLibraries() が来るとまずいようです。 かとんぼ wrote: > しかし CoFreeUnusedLibraries() はこのマクロ以外では、 > ole_event_free() でしか呼ばれて無いですね。動作そのものには影響無 > いようですが、どこかたくさん呼んでもらえる場所に移動する必要あり? Yamamoto さん wrote: > ・ Yamamoto (2004/06/14 12:33) > うーん、他の場所に動かしても、それが二つのRelease()の間で呼ばれ > てしまうと、やはりクラッシュすると思います。(二つのRelease()は離 > れているかもしれない) > > COMの設定に問題があるのかと色々試していたら、これでも落ちなくな > りました。 > Index: win32ole.c =================================================================== RCS file: /var/cvs/src/ruby/ext/win32ole/win32ole.c,v retrieving revision 1.22 diff -u -w -b -p -r1.22 win32ole.c --- win32ole.c 8 May 2004 03:54:51 -0000 1.22 +++ win32ole.c 14 Jun 2004 02:18:19 -0000 @@ -588,7 +588,7 @@ ole_raise(hr, exc, fmt, va_alist) void ole_uninitialize() { - OleUninitialize(); + CoUninitialize(); gOLEInitialized = Qfalse; } @@ -598,7 +598,7 @@ ole_initialize() HRESULT hr; if(gOLEInitialized == Qfalse) { - hr = OleInitialize(NULL); + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(FAILED(hr)) { ole_raise(hr, rb_eRuntimeError, "Fail : OLE initialize"); } > 問題は、なぜこうすると落ちないのかわからないということと、CoInitializeEx > は Win98(またはWin95+DCOM)や WinNT4.0 以降で使える関数なので、古いOSで > は使えないということです。 > > 私も COM に詳しくはないので、何か必要な設定を見逃しているのかもしれません > が、どうも使い方の問題というよりShell.Application のバグのような気がします。 > > ・ Yamamoto (2004/06/14 12:52) > あと、COINIT_MULTITHREADED だと CoFreeUnusedLibraries() がすぐ解放せずに、 > 10分後に解放するようスケジュールすると書いてあったので 12分待ってから > FolderItemVerb#Release()を呼んだのですが、それでも落ちませんでした。 -- 北島雅博(かとんぼ)