USB経由でメモリカードリーダーがつながっていて、しかもメモリが刺さっていたらなんかする、というプログラムを ruby で書こうと思い。
ドライブが存在して、そのドライブにメモリカードが刺さっている状態なら黙って真を返す関数というのがあるといいなと思ったんだが、見あたらなかった。
ドライブの 存在/非在 とはちょっと違うので、FileTest.directory? とか FileTest.exist? は、この目的には合わない。
やっぱりドライブなどというものは存在しない世界が主たるターゲットなので、そんなものはなさそうだ(見落としてる?)
というわけで、書いてみた:
require 'Win32API' module FileTest GetVolumeInformation = Win32API.new( 'Kernel32.dll', 'GetVolumeInformationA', 'ppippppi', 'n' ) end def FileTest.drive_ready?( path ) if /^([a-z]+\:)/oi===path args=[ # BOOL GetVolumeInformation( $1+'\\', # LPCTSTR lpRootPathName, '\0'*1024, # LPTSTR lpVolumeNameBuffer, 1024, # DWORD nVolumeNameSize, '\0'*4, # LPDWORD lpVolumeSerialNumber, '\0'*4, # LPDWORD lpMaximumComponentLength, '\0'*4, # LPDWORD lpFileSystemFlags, '\0'*1024, # LPTSTR lpFileSystemNameBuffer, 1024# DWORD nFileSystemNameSize ] # ); 0!=FileTest::GetVolumeInformation.call( *args ) else raise "bad path <#{path}> in FileTest.drive_ready?" end end
最初は GetFileAttribute だと思ったんだが、ディスクを刺せというプロンプトが出てしまう。
で。いろいろ試した結果。どうも GetVolumeInformation が正解らしい。引数がもっと少ない方が呼びやすいんだが、見あたらなかった。
手元で動かす気しかないつもりで書いたので、ドライブレター + コロン の形式しかサポートしてないし、決めうちで GetVolumeInformationA*1にしているし、いい加減な例外を投げている。バッファの長さも 1024 で決めうち。
製品に入れるのには不十分だが、手元で使うには十分なので、同じことで悩んでいる人のためにここにソースを書いてみた。
それにしても。
こういうときって、勝手に FileTest とかに入れちゃうのが筋なのか、それとも自分でモジュールを定義するのが筋なのか。
あまり気にせず入れちゃったけど。
*1:つまり、GetVolumeInformationWではなく