antenn-a
company profile

MFC航海日記 十二日目(複数のファイルをごみ箱へ移動する)

今日は、先日書いた「ごみ箱へ移動する」の第二弾である。
現在開発している「File Eater for Windows」はファイルを消すソフトであるので、当然ファイルを消せなければ意味がない。更に、複数のファイルを消す事ができなければ「御利益」が薄いので、一回でたくさんのファイルを消せるようにしようと思う。
そこで、まずは消し去りたいファイルのリストを作成し、前に使ったルーチンを呼ぶ事で問題の解決を計った・・が・・しかし、うまくいかない。
普通に消そうとすると、消せるファイルもあるし、消せないファイルもある。どうゆうことだ?何度やってもだめ。消せないファイルの数は一定ではなく、ボタンを押すタイミングなどで消せる個数が違う。なんでじゃ?わけわからん。そこで筆者はとんでもない解決法を選択した。この選択はプログラマーの基本ともいえるし、プログラマーでなくとも使っている方法であろう。
その方法とは・・・

分かってるやつにメールで聞く!

これが基本である。

prev

そこで、今回はWindowsソフトで古くから有名な「卓駆☆for Windows」を開発している(株)コム様にメールを出す事にした。
この卓駆☆for WindowsはWindows 3.1の頃から愛用しているソフトで、もちろんごみ箱へファイルを移動することもできる。あたりまえだが、私と(株)コム様とは何の関係もないし、いままでメールを書いた事すらない。もちろんメールのタイトルは「始めまして」である。
相手は株式会社なので学生相手にちゃんと答えてくれるかどうかかなり不安だったが、さすがである、次に日にさっそくメールが返ってきた。メールの内容は以下のとおり、

prev

神奈川工科大学情報工学科 榎本 繁 様

いつもコムのアプリケーションをご愛顧いただきありがとうございます。 さて、早速ですが、ご質問について回答いたします。

プログラムそのものは、企業秘密ですから、提示できませんが、 ヒントなら提示できるかと思います。参考になれば幸いです。

|としているのですが、消せるファイルと消せないファイルが存在して、 |消せない場合「ファイルシステムエラー」と表示されてしまいます。

ごみ箱へ移動できるファイルとできないファイルの違いが不明ですから 明確に回答できませんが、Windows NT4.0 の SP1 においては、 日本語全角文字を含む複数のファイルを移動した場合に、先頭の ファイル名しか移動できない。という、OSのバグがあります。 これは、SP3で回避されています。

それ以外で、以下について気がつくことは、

BOOL SearchFileDialog::MoveFileRecycleBin( CString path )
{
    static  char  tmp[ 10000 ];
    LPCSTR  buf = path.GetBuffer( path.GetLength() );
    strcpy( tmp, buf );
    path.ReleaseBuffer();
  
    SHFILEOPSTRUCT  FileOp;

    FileOp.fFlags = FOF_ALLOWUNDO;
    FileOp.fFlags = FOF_SILENTFOF_ALLOWUNDO
                  | FOF_SIMPLEPROGRESS
                  | FOF_NOCONFIRMATION;
    FileOp.hwnd = NULL;
    FileOp.wFunc = FO_DELETE;
    FileOp.pFrom = tmp;
    FileOp.pTo = NULL;
    FileOp.hNameMappings = NULL;
    FileOp.lpszProgressTitle = NULL;

    return ! SHFileOperation( &FileOp );
}

複数のファイル移動する場合は、上記処理では、問題があります。 FileOp.pFrom = tmp; に誤りがあるからです。 SHFileOperation の ヘルプには、 pFrom の説明が以下のように なっています。

Pointer to a buffer that specifies one or more source file names.
Multiple names must be null-separated. The list of names must be
double null-terminated

単一ファイルでも double null は必要です。削除対象のファイル名の 末尾は、double null としてみて下さい。

以上


prev

なるほど・・・Double Null ターミネータを埋め込まねばならないらしい。そこで、ダブルヌルを埋め込んでみると・・・やった!全部きれいさっぱり消えるではないか!!
書き換えたコードを以下に示す。
BOOL SearchFileDialog::MoveFileRecycleBin( CString path )
{
  static  char  tmp[ 10000 ];
  LPCSTR  buf = path.GetBuffer( path.GetLength() );
  strcpy( tmp, buf );
  path.ReleaseBuffer();

  //ここでダブルヌルにする。
  char* p  = tmp + strlen( tmp );
  *( p + 1 ) = 0;


  SHFILEOPSTRUCT  FileOp;    
  
  FileOp.fFlags = FOF_SILENT|FOF_ALLOWUNDO
  |FOF_SIMPLEPROGRESS|FOF_NOCONFIRMATION;
  FileOp.hwnd = NULL;
  FileOp.wFunc = FO_DELETE;    
  FileOp.pFrom = tmp;
  FileOp.pTo = NULL;
  FileOp.hNameMappings = NULL;
  FileOp.lpszProgressTitle = NULL;    

  return ! SHFileOperation( &FileOp );
}
上記のコードで動作が確認された。
後は、消したいファイルの順番にこの関数を呼んであげればOKである。


antenn-a

prev next


antenn-a