デジカメ(Nicon D3300)をPCにUSB接続すると外部ドライブとして認識せずにリムーバブル記憶域になってしましまい単純なファイルコピーコマンドが使えません。

調べたところD3300はWindows Portable Device(WPD)というデバイスらしくそれ用のコードでないといけないようでその方法を紹介します。

実装内容

今回やりたいことは以下になり、すべてのコードが実行後にアプリを終了させたかったためConsoleアプリとして作成しました。

今回のソースはこちらのGitにアップしておきました。

  1. PCに接続された12台のD3300からローカルの指定したフォルダに写真をコピー
  2. コピーが終了したらD3300(SDカード)内のファイルを削除
  3. ファイル削除が終わったらアプリ終了
1台のカメラ接続でローカルに写真をコピー

WPD: Transferring Contentから『WPD: Enumerating Content Source Code』をダウンロードします。この記事にコピーの手順が書いてありますが、ちょっとわかりにくい部分もあるんで簡単に説明します。

まず PortableDevices.cs にコピーの関数を追加します。

PortableDevices.cs

unsafe を使っているので Menu > Project > PortableDevices Properties... > Build の Allow unsafe code にチェックを入れてください。allowUsafeCodeOn

次に Program.cs にDownloadFile関数を呼び出すコードを追加します。ハイライン部分がそれになります。これで1台のデジカメで写真のコピーができるはずです。

Program.cs

複数台のカメラに対応したコピー

ソースを読んだ感じこのコードのままで複数台対応できるはずなんですが、なぜか2台目以降を認識してくれなかったため PortableDevices.cs のRefresh関数を変更します。(以下は2台を認識させるためのコードです。)

PortableDevices.cs

ハイライトになっている部分の説明

  • vid_04b0 -> ベンダーID
  • pid_0433 -> プロダクトID
  • ******* -> 端末固有ID(この記事ではIDは伏せておきます)
  • {6ac27878-a6fa-4155-ba85-f98f491d4f33 -> 詳しくはわかりませんが外部デバイスであることを示しているようです。

手っ取り早くこれらを調べるにはRefresh関数のオリジナルコードに Console.Writeline を追加して調べてみるのがいいです。一応書いておくと以下のように。

 

D3300のSDカードからコピーした写真を削除

WPD: Transferring Contentのコメント欄にChristopheさんが書き込みをしています。次のURLからダウンロードしてください。

http://dl.dropbox.com/u/40603470/WPDDeletingContent.zip

PortableDevices.cs を開けてDeleteFile関数とStringToPropVariant関数をコピーしてきてそれをPortableDevicesプロジェクトPortableDevices.cs に追加します。

Program.csのDisplayFolderContents関数にDeleteFile関数を呼び出すコードを追加します。そうするとDisplayFolderContents関数は以下の様なコードになります。

これでコピー後にファイルが削除されているはずです。

並列処理にする

このままだと12台コピーし終わるまでにかなり時間がかかってしまいますので Program.cs のMain関数内を並列処理に書き換えました。