スキップしてメイン コンテンツへ

 none
ReadDirectoryChangesW()でGetLastError()のエラーコード50が出力される。 RRS feed

  • 質問

  • こんにちは。

    今、ReadDirectoryChangesW()でエラーとなり困っています。

    開発環境 Visual Studio 2008 SP1 、Windows7 64bit

    やりたいことは、WPDデバイスのファイル名変更や更新などの情報をReadDirectoryChangesW()で取得したいと考えています。

    1. インターフェイスクラスGUIDにWPDのGUIDを設定し、SetupDiGetClassDevs()、SetupDiEnumDeviceInterfaces()、        SetupDiGetDeviceInterfaceDetail()を使ってファイルパスを取得する。

    2. 1のファイルパスをCreateFile()に渡して、モニタしたいディレクトリのハンドルを取得する。

    3. 2のハンドルをReadDirectoryChangesW()に渡して、変化が起きたファイル名とその変化(ファイル操作)の情報を取得する。

    この流れの処理をしたいと考えています。

    今の現状は3.のところで、GetLastError()のエラーコード(50)が出てしまっている状況です。

    試しに1の処理を飛ばして、2.CreateFile()にファイルパスとして”¥¥.¥C:¥”を渡してみると、Cドライブのファイルの変化は取得できました。

    解決策やアドバイスをいただけないでしょうか。情報お持ちでしたら、よろしくお願いいたします。

    • 移動 星 睦美 2014年12月4日 4:15 Visual C++
    2014年11月25日 6:58

回答

  • > MSCモードで実行した場合も、GetLastError()のエラーコード(50)となってしまいました。
    > 何か他に原因があるのでしょうか?

    CreateFile() API でオープンしたハンドルが、WPD に紐づけられた "デバイス ハンドル" であるためと考えられます。
    そもそも、ご質問時に書かれている方法で取得されるハンドルは、"ディレクトリ ハンドル" ではなく "デバイス ハンドル" です。
    同じハンドルであっても、そのハンドルに紐づけられるデバイスが全く異なります。
    私が「MSC モードで接続すれば動く」と言ったのは、
    「MSC モードで PC に接続すれば、WPD はストレージ デバイスとしても認識されるので、
      ローカル ストレージと同様のアクセスが可能になる。」
    ということです。
    つまり MSC モードで接続すれば WPD 内のストレージにもドライブ レターが割り当てられるので、ローカル ストレージ アクセスと同様に、ディレクトリ パスを 1st パラメータとした CreateFile() API コールでディレクトリ ハンドルをオープンし、そのハンドルで ReadDirectoryChangesW() コールを行えば、この API は機能するはず。。。という意味で書きました。

    先に示したサイトをご覧いただければ、MTP モード / MSC モードの違いをご理解いただけると思ったので、CreateFile() API での対象パスもおのずと変わってくることを明記しなくても自明だと思い、そこまで説明しませんでした。
    (私の説明に不足があったようで、申し訳ありませんでした。)

    ご提示されている Setup API コールで取得したデバイス インスタンス パスは、WPD 全体を指すデバイスへのパスであり、WPD 内の "ストレージ デバイス" および WPD ストレージ内の "ルート ディレクトリ" を指すパスではありません。
    WPD へのデバイス インスタンス パスを 1st パラメータとした CreateFile() API コールで、なぜ「モニタしたいディレクトリのハンドル」が取得できるとお考えになったのでしょうか?

    • 回答としてマーク 星 睦美 2014年12月12日 5:40
    2014年11月26日 2:23
  • > 今の現状は3.のところで、GetLastError()のエラーコード(50)が出てしまっている状況です。

    PC - WPD 間の通信が MTP で行われているのであれば、当然の結果と考えられます。
    WPD でも MSC モードをサポートしているデバイス (私の手元にある Xperia は、MTP/MBC のモード切り替えができる) もあるので、MTP モードではなく MSC モードで接続すれば、ReadDirectoryChangesW() API は機能すると思います。
    MSC モードをサポートしない WPD では、WPD ストレージへの I/O はファイル I/O にはならない(当然)ので、ReadDirectoryChangesW() API は意味が無いと思います。

    ------------------------------------------------------------
    ファイル転送の「MTP」と「MSC」はどう違うの? - いまさら聞けないAndroidのなぜ
    http://news.mynavi.jp/news/2014/01/13/051/
    ------------------------------------------------------------

    • 回答の候補に設定 星 睦美 2014年12月3日 1:53
    • 回答としてマーク 星 睦美 2014年12月12日 5:40
    2014年11月25日 7:41

すべての返信

  • > 今の現状は3.のところで、GetLastError()のエラーコード(50)が出てしまっている状況です。

    PC - WPD 間の通信が MTP で行われているのであれば、当然の結果と考えられます。
    WPD でも MSC モードをサポートしているデバイス (私の手元にある Xperia は、MTP/MBC のモード切り替えができる) もあるので、MTP モードではなく MSC モードで接続すれば、ReadDirectoryChangesW() API は機能すると思います。
    MSC モードをサポートしない WPD では、WPD ストレージへの I/O はファイル I/O にはならない(当然)ので、ReadDirectoryChangesW() API は意味が無いと思います。

    ------------------------------------------------------------
    ファイル転送の「MTP」と「MSC」はどう違うの? - いまさら聞けないAndroidのなぜ
    http://news.mynavi.jp/news/2014/01/13/051/
    ------------------------------------------------------------

    • 回答の候補に設定 星 睦美 2014年12月3日 1:53
    • 回答としてマーク 星 睦美 2014年12月12日 5:40
    2014年11月25日 7:41
  • お馬鹿 様の返信が完全な回答と思うので蛇足ですが・・・。

    GetLastError の戻り値 50 は ERROR_NOT_SUPPORTED と思われ、ReadDirectoryChanges がサポートされてないであろう事が推測されますね。

    WPD に要素?変更監視機能があったかどうか知らないですが、監視したいなら WPD オブジェクト機能でないとダメじゃないかな?

    2014年11月25日 8:46
  • お馬鹿さま 返信ありがとうございます。

    途中経過です。

    MSCモードで実行した場合も、GetLastError()のエラーコード(50)となってしまいました。

    何か他に原因があるのでしょうか?

    以上です。

    2014年11月25日 9:27
  • kyano30様返信ありがとうございます。

    やはりサポートされていないのですかね。

    WPDオブジェクト機能について知識がないのでちょっとわからないです。

    以上です。

    2014年11月25日 9:29
  • > やはりサポートされていないのですかね。

    ハンドル取得できてるみたいなので、取得パスはきちんとマウントパスになってて、処理的な間違いはなさそうですから・・・

    WPD の構造を考えると MSC モードでも非サポートになってる可能性が高いですかね。

    ReadDirectoryChanges で WPD デバイスの変更監視をするのは、やはり無理があるという感じがします・・・。

    > WPDオブジェクト機能について知識がないのでちょっとわからないです。

    WPDオブジェクト機能 って書いたけど 「WPD API の機能」 という意味合いで書きました。(COM APIですから・・・)

    ざっと見てみたら、 Supported Tasks in WPD Applications の中に「デバイスイベントのモニタ」があるのでイベント次第で監視になるかも?

    自分はイベント監視経験ないですし、可能性はかなり低いのですけど・・・。

    ---------------------------------------------------------------------------------------------------

    お馬鹿 様の言われるように Setup API からだから取得パスは「デバイスインスタンスパス」っぽいのかな?

    それならば機能するはずありませんね、失礼しました。

    てっきり、マウントパスをきちんと取得して FTP フォルダと同様な感じかと想像しちゃいました。



    • 編集済み kyano30 2014年11月26日 7:17 取消できなかった・・・
    2014年11月25日 13:30
  • > MSCモードで実行した場合も、GetLastError()のエラーコード(50)となってしまいました。
    > 何か他に原因があるのでしょうか?

    CreateFile() API でオープンしたハンドルが、WPD に紐づけられた "デバイス ハンドル" であるためと考えられます。
    そもそも、ご質問時に書かれている方法で取得されるハンドルは、"ディレクトリ ハンドル" ではなく "デバイス ハンドル" です。
    同じハンドルであっても、そのハンドルに紐づけられるデバイスが全く異なります。
    私が「MSC モードで接続すれば動く」と言ったのは、
    「MSC モードで PC に接続すれば、WPD はストレージ デバイスとしても認識されるので、
      ローカル ストレージと同様のアクセスが可能になる。」
    ということです。
    つまり MSC モードで接続すれば WPD 内のストレージにもドライブ レターが割り当てられるので、ローカル ストレージ アクセスと同様に、ディレクトリ パスを 1st パラメータとした CreateFile() API コールでディレクトリ ハンドルをオープンし、そのハンドルで ReadDirectoryChangesW() コールを行えば、この API は機能するはず。。。という意味で書きました。

    先に示したサイトをご覧いただければ、MTP モード / MSC モードの違いをご理解いただけると思ったので、CreateFile() API での対象パスもおのずと変わってくることを明記しなくても自明だと思い、そこまで説明しませんでした。
    (私の説明に不足があったようで、申し訳ありませんでした。)

    ご提示されている Setup API コールで取得したデバイス インスタンス パスは、WPD 全体を指すデバイスへのパスであり、WPD 内の "ストレージ デバイス" および WPD ストレージ内の "ルート ディレクトリ" を指すパスではありません。
    WPD へのデバイス インスタンス パスを 1st パラメータとした CreateFile() API コールで、なぜ「モニタしたいディレクトリのハンドル」が取得できるとお考えになったのでしょうか?

    • 回答としてマーク 星 睦美 2014年12月12日 5:40
    2014年11月26日 2:23
  • お馬鹿様返信ありがとうございます。

    プログラミングを初めて数か月なので、"デバイス ハンドル" と、"ディレクトリ ハンドル" の違いを認識できていませんでした。

    ディレクトリをモニタするにはReadDirectoryChangesW() には"ディレクトリ ハンドル"を渡してやる必要があるということでいいですかね。

    まだまだ、わからないことばかりなので頑張って勉強していきたいと思います。

    2014年12月2日 4:35
  • > ディレクトリをモニタするにはReadDirectoryChangesW() には
    > "ディレクトリ ハンドル"を渡してやる必要があるということでいいですかね。

    WPD 側の PC 接続時通信プロトコルが MSC モードの場合は、その認識で良いと思います。
    (くどいようですが。。。。MTP/PTP モードでは、この API は意味を持ちません。)

    なお MSC モードで PC - WPD を USB 接続し、WPD 内のストレージに対して ReadDirectoryChangesW() API で監視を行った場合、監視中はタスク トレイからの「安全な取り外し」は常に失敗することになりますので、ご注意ください。
    (WPD に限らず、USB メモリでも同じことですが。)

    2014年12月2日 6:13