Windows XPでデジタルカメラの写真のプロパティを取得したい – プログラミング – Home

Windows XPでデジタルカメラの...
 
通知
すべてクリア

[解決済] Windows XPでデジタルカメラの写真のプロパティを取得したい


あき
 あき
(@あき)
ゲスト
結合: 24年前
投稿: 47
Topic starter  

Visual Studio 2008/MFC にて、デジタルカメラをUSB接続し、カメラ上の画像が保存さ
れているフォルダをシェルで開いて画像をドラッグ&ドロップすることにより自身が管
理するハードディスク(ファイルシステム)にコピーする機能を持つアプリケーション
を作成しています。

条件は、

・デジタルカメラをUSB接続した時にドライブとしては見えない。(ポータブルデバイ
ス)
・デジタルカメラにある画像/動画の中身はそのまま、且つファイル時刻もデジタルカ
メラ上の時刻そのままとしたい。

Vista以降ではできるようになったのですが、XPでできずに困っています。
出来ない部分は、画像、もしくは動画の撮影時刻と言ったプロパティをXP取得では取得
できません。
なお、Windows 2000はサポート対象外です。

ざっと流れを以下に記述します。(Vista以降の場合)

1. 作成アプリケーションにデジタルカメラからドラッグ&ドロップ
→ ドロップされた画像/動画のITEMIDLISTを取得

2. ITEMIDLIST→IShellItem
SHCreateItemFromIDList(Vista以降)
SHCreateShellItem(XP)

3. IShellItemからIPropertyStoreを取得
IShellItem::BindToHandler(BHID_PropertyStore) ← Vista以降でないと利用不可

4. IPropertyStoreから時刻や元のファイル名などを取得

XPでIShellItemからプロパティを取得する方法をご存じないでしょうか。
逃げの対策としては、JPEG(Exif)の場合はファイルの内容をコピーした後でGDI+で読み
込んでプロパティを取得しています。

この方法ではaviやmovといった動画には対応できないと思います。
ちなみに、上記方法で(Vista以降では)動画ファイルのプロパティもJPEG同様に取得出
来ています。

以上、宜しくお願いいたします。


引用未解決
トピックタグ
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

> XPでIShellItemからプロパティを取得する方法をご存じないでしょうか。
IShellItem からじゃないけど、IPropertySetStorage を得れば取れるかと。
IPropertySetStorage は StgOpenStorageEx() か IShellFolder::BindToStorage() で得
られる。ただ、問題もあるらしい↓(上から順番に見てみる事を勧める)

http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+200511/05110054.txt
http://homepage1.nifty.com/MADIA/vc/vc_bbs/200612/200612_06120034.html
http://rarara.cafe.coocan.jp/cgi-bin/lng/vc/vclng.cgi?print+200804/08040018.txt

上記は StgOpenStorageEx() 絡みでの情報だけど IShellFolder::BindToStorage() から
でも同じ問題が起こるのかどうかは知らない。
# 昔 IShellFolder::BindToStorage() で実装した時は↑url内で書かれている事等までは
# 気にしなかったからなぁ


返信引用
あき
 あき
(@あき)
ゲスト
結合: 24年前
投稿: 47
Topic starter  

gak様

ヒントありがとうございます。
IPropertySetStorageの取得はやってみたのですが、Vistaでは取得可能、XPでは「イン
ターフェースがサポートされていません」(HRESULT=80004002)によって
IPropertySetStorageが取得できませんでした。

↓ こんな感じのものですがS_OKが返りません。

CComPtr<IPropertySetStorage> pStorage;
pDesktopFolder->BindToStorage(lpItemIDListAbsolute, NULL,
IID_IPropertySetStorage, reinterpret_cast<void**>(&pStorage);

ファイルシステム上のファイルではないから...ということなのかな、と思っていま
す。

このようなファイルのプロパティは、XPであってもエクスプローラでは確認することが
可能です(Exifでなくても)。
なので何か手段が提供されていないものかと思うのですが難しいですね。


返信引用
あき
 あき
(@あき)
ゲスト
結合: 24年前
投稿: 47
Topic starter  

追加でgak様からの返信内のリンクにありますシャノン様が提示された方法で試してみま
した。
IPersistFileをMSDNで調べていたらIPersistIDListなんてものがあったので、これか!
と。

CComPtr<IPropertySetStorage> pPropetySet;

CLSID clsid;
::CLSIDFromString(L{eb9b1153-3b57-4e68-959a-a3266bc3d7fe}, &clsid);

::CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IPropertySetStorage,
reinterpret_cast<void**>(&pPropetySet));

CComPtr<IPersistIDList> pPersistIDList;
pPropertySet.QueryInterface(&pPersistIDList); ← HRESULT=80004002「イン
ターフェースがサポートされていません

これがXPでうまくいけばJPEG以外の場合なども考えようかと思いましたがそこまでたど
り着けず...

やはりファイルシステムオブジェクトでないとXPでは駄目なんですかね。


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

> Vistaでは取得可能、XPでは「インターフェースがサポートされていません」
vista では取れているって事は環境の違いに因るものなのかなぁ…

> 4. IPropertyStoreから時刻や元のファイル名などを取得
作成/更新/アクセス日時と元のファイル名が取れればOKと単純に考えて良いのだろうか?
もしそうならばシンプルに、

// IShellFolderPtr shellFolder;
// ITEMIDLIST *idListRelative;
WIN32_FIND_DATA fd;
::SHGetDataFromIDList(shellFolder, idListRelative, SHGDFIL_FINDDATA, &fd,
sizeof(fd));

で方が付いたりしないだろうか?

> なので何か手段が提供されていないものかと思うのですが難しいですね。
例えば、shell32.dll には「SHStgOpenStorageW / SHStgOpenStorageA」なんていう如何
にもな名の非公開関数が存在している。これとかを利用すれば可能なのかもしれないね。
# 正式に公開されている方法だけでも可能で其れを俺が知らないだけ、という可能性の方が
# はるかに高いとは思うが。


返信引用
あき
 あき
(@あき)
ゲスト
結合: 24年前
投稿: 47
Topic starter  

gak様

返信ありがとうございます。

>> 4. IPropertyStoreから時刻や元のファイル名などを取得
>作成/更新/アクセス日時と元のファイル名が取れればOKと単純に考えて良いのだろう
か?
>もしそうならばシンプルに、

>// IShellFolderPtr shellFolder;
>// ITEMIDLIST *idListRelative;
> WIN32_FIND_DATA fd;
> ::SHGetDataFromIDList(shellFolder, idListRelative, SHGDFIL_FINDDATA, &fd,
sizeof(fd));

>で方が付いたりしないだろうか?

IPropertySetStorageの取得に関して、Vista/7 で OK なのに XP では NG というのはシ
ェルのバージョンの違いと言うことくらいしか理由が思い付きません。XPが動作するPC
は、仮想PC含め3台で同じ挙動を示します。(全てSP3)

ご提示頂いたSHGetDataFromIDListを試してみましたが、結論としてはNGでした。これは
Vista/7 でも NG です。
これについてはどうもデジタルカメラ内のアイテム(ファイルシステムオブジェクトで
はないということかも)はサポートされないようです。
これが事実であるということを示す情報は見つけられていません。しかしながら、事実
としてこちらでの実機確認作業においてはファイルシステムオブジェクトに対しては利
用可、デジタルカメラ内のアイテムに対しては利用不可(HRESULT=E_FAIL)でした。

後はSHStgOpenStorageW/SHStgOpenStorageAですね。ただ引数を調べないと試せませんの
で少々時間が掛かりそうです。
ここまで一連の質問内容について、XP のエクスプローラでは「出来ている」ので、ひょ
っとすると非公開APIによって出来るかも、というのは期待できるかもしれません。

一旦クローズしたいと思います。

gak様。お付き合い頂きありがとうございました。重ねて御礼申し上げます。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

# どうも、aetos です。昔はシャノンと名乗っていた者です。

IShellFolder2::GetDetailsEx でできませんかね…?


返信引用
あき
 あき
(@あき)
ゲスト
結合: 24年前
投稿: 47
Topic starter  

シャノン様

助言ありがとうございます。無事出来ました。

フォルダのITEMIDLIST
lpItemIDListParent

画像や動画のITEMIDLIST
lpItemIDListChild

CComPtr<IShellFolder> pShellFolder;
pDesktopFolder->BindToObject(lpItemIDListParent, NULL, IID_IShellFolder,
reinterpret_cast<void**>(ppShellFolder));

CComPtr<IShellFolder2> pShellFolder2;
pShellFolder.QueryInterface(&pShellFolder2);

pShellFolder2->GetDetailsEx(lpItemIDListChild, &PKEY_DateModified, &variant);

VariantTimeToSystemTime(variant.date, &systemTime);←SYSTEMTIMEが取れました。

おかげさまで無事にXPでも目的が達成できます。
一つクリアできたので他のデジカメでも同じように日時が取れるかと言う確認を始めま
した。

すると、今度は Vista/7 において更新日時が取れないカメラが出てきました。(XPでは
上記の方法で取れる)
カメラの機種に依存しているようです。そんなに多数のデジカメで試しているわけでは
ありませんが、上記方法において、あるカメラだと XP/Vista 共にOK、あるカメラでは
XP だとOK しかしながら Vista/7 だと E_INVALIDARG が返ってくる、なんてことが起き
ます。

Vista/7 において HRESULT=E_INVALIDARG が返ってくる場合は、そのファイル(アイテ
ム)をエクスプローラの「詳細」プロパティで見てもやはりその情報はないという扱い
になっています。なので仕方がないと言えば仕方がありません。釈然としないものがあ
りますが...XP では取得できるわけですから。

このとき、Vista 以降なのでIShellItem2::GetFileTimeを使ってみましたがやはり駄
目。
当初の質問内容からは外れますのでまた頑張ってみますが、OS によって処理を変えなく
てはならない、カメラによって(且つOSにも依存して)日時が取れる/取れないがある
とはなかなかの曲者です。
あくまで私個人の感覚ですが、こんな部分についても一眼レフはしっかり作ってある、
コンパクトデジカメは結構いいかげんに作ってある...そんな風に思えました。

いずれにしても大きな進歩です。大変助かりました。ありがとうございました。


返信引用
あき
 あき
(@あき)
ゲスト
結合: 24年前
投稿: 47
Topic starter  

aetos様

名前誤ってました。失礼致しました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました