特になし

とりとめもなくダラダラ書いてみようという感じ・・・

過去の投稿日別表示

[ リスト | 詳細 ]

全1ページ

[1]

FindFirstFileEx

以前、ニコニコ動画から「 Bad Apple!! 」という動画をダウンロードしたことがあったのだが、どこに保存したのかわからなくなってしまった。Windows7 ではスタートボタンをクリックすると一番下に「プログラムとファイルの検索」なるテキストボックスが現れる。一見、これで検索をすれば良さそうであるが、大抵、どういう関連付けなのかわからないプログラムもリストアップされるし、コマンドプロンプトで dir で検索する方が速いような気がしてたので、dir を使って
C:\>dir bad*.* /s
で検索をした。すると、途中で background0005.png というファイルが出力された。このファイル名にはどこにも "bad" が含まれていないのに、なぜ?
このファイルは
C:\Program Files (x86)\Dell Webcam\Dell Webcam Central\Scriptlets\FacePaste\surfer_files
というフォルダに入っていたのだが、このフォルダを D:\ にコピーして、
D:\surfer_files>dir bad*.*
としても、やはり、background0005.png が出力される。
 
イメージ 1
 
しかも、他の background*.png は出力されない。ディスクのインデックスかディレクトリエントリが破損しているのかと思い、ディスクのチェックを行ってみたが、症状は同じだった。また、、自分で background0005.txt というファイルを作っても、これは dir bad*.* には引っかからない。
なんだか気持ち悪いので、Visual C++ で簡単なプログラムを作って検証してみることにした。
 
「 Windows API のファイル検索をする関数って、なんだっけ?」と思うたびに、Google の検索キーワードに findfirstfile と入力してしまう。そして検索結果を見て、それが Windows API とは別のものであることに気づく・・・。Windows API のファイル検索を行う関数は FindFirstFile、FindFirstFileEx である。(しかし、このブログを書いたおかげで、もう二度と間違うことはないような気がする。「最初のファイルを見つける」と覚えればいいのだ。)検索結果から MSDN のページを探し出し、FindFirstFile の引数を確認して次のコードを書いた。
int _tmain(int argc, _TCHAR* argv[])
{
    WIN32_FIND_DATA wfd;
    HANDLE find = FindFirstFile( _T("D:\\surfer_files\\bad*.*"), &wfd );
    if( INVALID_HANDLE_VALUE != find ) {
        _tprintf( _T("%s"), wfd.
ここで、wfd.. を打ったところで、IntelliSense によって表示されたメンバー一覧を見てようやく思い出した。
WIN32_FIND_DATA.cAlternateFileName の存在を。そう、WIN32_FIND_DATA.cFileName はロングファイルネームで、WIN32_FIND_DATA.cAlternateFileName は 8.3 形式 ( 拡張子を含まない部分 8 文字、拡張子 3 文字 ) のファイル名である。問題の background0005.png では、この短いファイル名が BAD なんとかになっているのだろう。
dir /? で、dir のオプション一覧を見てみると、/X で「長い名前の前に短い名前を表示する」とあったので、
D:\surfer_files>dir /x
としてみた。
 
イメージ 2
 
一件落着である。
それにしても、紛らわしい仕様である。短いファイル名を検索対象にしないオプションはないのだろうかと思って、再度、dir /? でオプション一覧を見てみたが、それらしいものはなかった。では、API ではどうなっているのだろうと思い、MSDN を調べてみた。
FindFirstFile は今まで何度か使ったことがあったが、念のため見てみると、プロトタイプは、
HANDLE FindFirstFile(
    LPCTSTR lpFileName,                   // ファイル名
    LPWIN32_FIND_DATA lpFindFileData // データバッファ
);
となっていた。やはり、「短いファイル名を検索対象にしない」というような指定をする余地はない。
 
FindFirstFileEx は今まで使ったことがなかったのだが、プロトタイプは

HANDLE FindFirstFileEx(
    LPCTSTR lpFileName,                    // 検索するファイル名
    FINDEX_INFO_LEVELS fInfoLevelId,   // データの情報レベル
    LPVOID lpFindFileData,                   // 返された情報へのポインタ
    FINDEX_SEARCH_OPS fSearchOp,    // 実行するフィルタ処理のタイプ
    LPVOID lpSearchFilter,                   // 検索条件へのポインタ 
    DWORD dwAdditionalFlags               // 補足的な検索制御フラグ
);
fInfoLevelId の説明は
fInfoLevelId
    返されるデータの情報レベルを表す、 列挙型を指定します。
となっていた。本来、
 
返されるデータの情報レベルを表す、 FINDEX_INFO_LEVELS 列挙型を指定します。
 
となっているはずなのだろう。リンク先が移動したか、翻訳されていない(日本語版のページがない)ために、リンクが削除されてしまったのだろうか。
fSearchOp についても同様で、
 
fSearchOp
    ワイルドカードとの照合以外のフィルタ処理タイプを表す、 列挙型を指定します。
 
となっていた。仕方がないので、本国の MSDN を見ることにした。
本国 MSDN ( http://msdn.microsoft.com/en-us/library/windows/desktop/aa364415(v=vs.85).aspx ) では、fInfoLevelId の説明は、やはり、
 
fInfoLevelId [in]
    The information level of the returned data.
    This parameter is one of the FINDEX_INFO_LEVELS enumeration values.
 
のようになっていて、FINDEX_INFO_LEVELS からリンクをたどることができた。
FINDEX_INFO_LEVELS のメンバーは次のようなものだった。
  • FindExInfoStandard FindFirstFile と同じ動作。
  • FindExInfoBasic      : WIN32_FIND_DATA に短いファイル名をセットしない。Windows Server 2008、Windows Vista、Windows Server 2003、Windows XP ではサポートされていない。Windows Server 2008 R2 と Windows 7 では使用可能。
Windows 2000 はどうなってるんだ?とツッコミを入れたくなるが、まぁ、それはおいておいて、この FindExInfoBasic だと、短いファイル名は拾ってこないわけだから、これなら、短いファイル名は検索対象にならないかもしれない。また、fSearchOp や、lpSearchFilter、dwAdditionalFlags は、短いファイル名を検索対象から外すという目的には関係なさそうだった。
とりあえず、FindExInfoBasic を使って、次のプログラムを書いてみた。
int _tmain(int argc, _TCHAR* argv[])
{
    WIN32_FIND_DATA wfd;
    HANDLE find = FindFirstFileEx( _T("D:\\surfer_files\\bad*.*"), FindExInfoBasic, &wfd, FindExSearchNameMatch, NULL, 0 );
    if( INVALID_HANDLE_VALUE != find ) {
        _tprintf( _T("%s"), wfd.cFileName );
        _tprintf( _T(" ( %s )\n"), wfd.cAlternateFileName );
        while( FindNextFile( find, &wfd ) ) {
            _tprintf( _T("%s"), wfd.cFileName );
            _tprintf( _T(" ( %s )\n"), wfd.cAlternateFileName );
        }
        FindClose( find ); 
    }
}
実行結果は次のようになった。

 
イメージ 3
 
なんだかなぁー、である・・・。

開く コメント(0)

開く トラックバック(0)

全1ページ

[1]


.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事