今回は、プロデルでUSB接続されたデジカメから、メモリカード内にある写真の一覧を調べたり、写真をコピーしたりしてみようと思います。

デジカメの機種によってはUSBケーブルで接続すると、メモリカードの内容を見たり、コピーしたりできるものがあります。ただこれらの操作は、エクスプローラだけで可能で、アドレスバーに書かれたパスをプロデルで指定しても、操作できません。
操作できない理由は、USBケーブルで接続した場合、PCとデジカメとの間ではメディア転送プロトコル(Media Transfer Protocol, MTP)という通常とは異なる方法でファイルをやりとりしているためです。
そこで、この記事では、プロデルからエクスプローラの機能を利用して、デジカメから画像をコピーする方法を説明します。
紹介するプログラムは、プロデル 1.5.853以降で対応しています。最新版をインストールしてからお試し下さい。
なお、ここで説明する方法は、MTPに対応したデジカメやポータブルプレーヤ、スマートフォンなどをUSB接続した場合に限って利用できる方法です。SDカードを直接PCに差し込んだ場合には、アドレスバーのパスをコピーするだけで、プロデルから簡単にファイルをコピーできます。
エクスプローラの機能にアクセスする
USB接続したデジカメは、エクスプローラを通じてアクセスできます。一方エクスプローラには、COM (Component Object Model)と呼ばれる他のアプリケーションから自分が持つ機能を利用できるようにする仕組みが用意されています。
COMは、エクスプローラやOffice製品、IEのアドイン、Adobe製品などで古くから利用されている技術で、機能の一部をCOMコンポーネントという形で他のプログラムからアクセスできるように設計されています。
「COM型」種類
(少し難しい話になりますので、ここは読み飛ばしても構いません)
プロデルでは、COMコンポーネントとして提供されている機能をプロデルのオブジェクトとしてアクセスするための「COM型」種類を用意しています。今回はCOM型を使ってエクスプローラの機能にアクセスします。
COMコンポーネントにはそれぞれ固有の番号(GUID)と名前(ProgID)が付けられており、これらはレジストリで管理されています。エクスプローラの機能を提供するコンポーネントのProgIDは、「Shell.Application」です。
プロデルで「COM型」種類を作る際に、ProgIDまたはGUIDを指定することで、そのコンポーネントを利用できるようになります。ただ、「COM型」のオブジェクトは、これ自身はコンポーネントの型情報を持っているだけです。COM型オブジェクトを作った後に、「インスタンスを作る」手順を呼び出すことで、ようやく機能にアクセスできるCOMオブジェクトを作ることができます。
接続したデジカメのメモリカードの内容を見る
さて、まずは、エクスプローラのアクセスするためのCOMオブジェクトを作り、エクスプローラからデジカメにアクセスして、フォルダの内容を表示するプログラムを作ってみます。

※以下のプログラムは、実際にデジカメデバイスを操作します。意図しない操作で撮影した写真等が消える可能性もありますので、プログラムを試す前に、必ずメモリカードにある写真を別の場所にすべてバックアップして下さい!操作は自己責任でお願いします
次のプログラムで「shellApp」変数にエクスプローラにアクセスするオブジェクトが作られます。
ShellApplicationというCOM型(「Shell.Application」)を作る ShellApplicationからインスタンスを作ってshellAppとする ソースパス=shellApp:BrowseForFolder(0, 「カメラ内のフォルダを選択して下さい」,0,「」) もしソースパスが無なら終了 (ソースパス:Items())のすべてのアイテムについてそれぞれ繰り返す アイテムのNameを報告する 繰り返し終わり
このプログラムを実行すると、最初にフォルダの選択画面が表示されます。ここでデジカメの名前のデバイスを選択して、その中のフォルダを選択して[OK]をクリックします。そうすると、そのフォルダにあるファイル名を調べることができます。

プログラム中のBrowseForFolderメソッドは、画面で選択したフォルダ情報(Folderオブジェクト)を得られるメソッドです。返されるフォルダ情報にはItemsメソッドがあり、このメソッドでフォルダ内にあるフォルダやファイルの情報の一覧を取得できます。一覧からアイテムを取り出すことで、ファイル名等の情報を調べられます。なおファイル名はNameプロパティで分かります。
このようにCOMオブジェクトは、C++等で開発されているため、メソッド名(手順名)やプロパティ名(設定項目名)が英単語表記になっています。
COMオブジェクトをプロデルでアクセスする場合には、文法も少し異なります。メソッド呼び出しは、『変数:メソッド名(引数)』のような文法で書きます。引数が無い場合にも、( )を必ず指定して下さい。プロパティは設定項目と同じように書きます。
デジカメのファイルをPCへコピーする
ファイルの一覧が取得できたところで、今度はそれらのファイルをPCへコピーしてみます。
Folderオブジェクトには、CopyHereメソッドがあります。コピー先のフォルダで、コピーしたいファイルを指定してCopyHereメソッドを呼び出せば、そのファイルをコピーできます。
なお、同じようにMoveHereを使ってファイルを移動させることもできます。ただし、ファイル名を変えたり、ファイルを消したりすることはMTPの仕様上できないようです。
コピー先のフォルダ情報を取得する
PC側の指定したフォルダのフォルダ情報を調べるには、エクスプローラのNamespaceメソッドを使います。このメソッドにパスを指定すると、該当するフォルダのフォルダ情報が得られます。
コピー先フォルダ=shellApp:Namespace(「[デスクトップ]デジカメ写真」)
フォルダ情報を取得した上で、『コピー先フォルダ:CopyHere(アイテム)』などと書くことで、該当するファイルをコピー先へコピーできます。
(ソースフォルダ:Items())のすべてのアイテムについてそれぞれ繰り返す アイテムのNameを報告する コピー先フォルダ:CopyHere(アイテム) 繰り返し終わり
あらかじめデバイス名とフォルダを指定してコピーする
プロデルで定期的にデジカメにある写真をコピーしたい時などは、その都度フォルダを選択していると面倒です。そこで、デジカメのデバイス名を指定して、フォルダをコピーできるようにします。
注意点として、画像の保存先が機種や状況によって異なることです。DCIMフォルダ内のフォルダの分類は、デバイスによって異なり、写真数が多い場合には複数のフォルダにまたがって保存される場合もあります。そのため自動化する場合は対象のデバイスをエクスプローラで確認しながら、パスを指定して下さい。
さて、エクスプローラにはツリーにデバイス名が表示されていますが、Namespaceメソッドに、このデバイス名を指定しても取得に失敗して「無」が返ってきてしまいます。

Namespaceメソッドでは、引数にデバイス名に対応する固有の識別子を指定する必要があるのですが、この表記が単純ではないため、プロデルで「~というデバイスを取得する」手順を作って、デバイス名を識別子を取得できるようにします。
先頭の「デバイス名」変数を使っているデジカメの名前に変えることで、そのカメラのファイルをコピーします。対象のフォルダはプログラム中盤の「ソースフォルダ」変数の代入文で指定しています。
デバイス名は、「Canon EOS Kiss X7」 ShellApplicationというCOM型(「Shell.Application」)を作る ShellApplicationからインスタンスを作ってshellAppとする デバイス名というデバイスを取得してデバイスフォルダとする もしデバイスフォルダが無なら「デバイスが見つかりません」と警告する ソースフォルダ=shellApp:Namespace(「[デバイスフォルダのPath]\SD\DCIM\100CANON」) コピー先フォルダ=shellApp:Namespace(「[デスクトップ]デジカメ写真」) (ソースフォルダ:Items())のすべてのアイテムについてそれぞれ繰り返す アイテムのNameを報告する コピー先フォルダ:CopyHere(アイテム) 繰り返し終わり 【デバイス名】というデバイスを、取得する手順 ルートアイテム=shellApp:Namespace(「」) (ルートアイテム:Items())のすべてのアイテムについてそれぞれ繰り返す もしアイテムのNameがデバイス名なら アイテムを返す もし終わり 繰り返し終わり 無を返す 終わり
このプログラムを実行すると、デジカメにある画像ファイルをPCの指定したフォルダにコピーしてくれます。
更新日やサイズなどファイルの情報を取得するには
フォルダ情報のGetDetailsOfメソッドを使うことで、ファイルの更新日やサイズなどの情報も調べられます。
例えばバックアップしていない写真のみをコピーするといった事もできるかと思います。
(ソースパス:Items())のすべてのアイテムについてそれぞれ繰り返す アイテムのNameを報告する Type=ソースパス:GetDetailsOf(アイテム,1) Size=ソースパス:GetDetailsOf(アイテム,2) ModifyDate=ソースパス:GetDetailsOf(アイテム,3) 「[アイテムのIsFolder] [ModifyDate] [Size] [Type]」を報告する 繰り返し終わり
まとめ
今回はCOMについての難しい話があり「なんだかCOMは難しそう」と思った方もいらっしゃるかもしれません。ただプログラムをみて、どこを直せば良いのか分かれば、今まではできなかったことがプロデルで実現できるかと思います。
今回取り上げたプログラムを作るに当たっては、VBAやC++のドキュメントを参考に作りました。Shell.ApplicationやVBAで検索すると、他にも色々な機能を、プロデルプラグインを入れること無く利用できます。情報を探してプロデル上で試してみると、プロデルをより便利に使いこなせるかと思います。