PowerShellのGetDetailsOf メソッドでプロパティの詳細情報のID番号と項目名を列挙します

Quick Edit Pencil
※PowerShell初心者
※下の方に画像が持つExif情報を列挙する方法もあります。

例えば、あるJPG画像(C:\IMG_0001.JPG)のカメラ機器のモデル名とExifの撮影日時に関する情報が欲しいとします。

1.

PowerShellでは、Get-ItemPropertやGet-ChildItemを使いFileInfoプロパティ取ることができます。
$path = "C:\IMG_0001.JPG"
Get-ItemProperty $path | Select-Object * | Format-List
$path = "C:\IMG_0001.JPG"
Get-ChildItem $path | Format-List -property *
結果: しかし、Get-ItemPropert等を使い取ることができるFileInfoプロパティには必要な情報がありません。
そこで、GetDetailsOfを使い、ファイルプロパティの詳細情報から必要な情報を取得します。
PSPath            : Microsoft.PowerShell.Core\FileSystem::C:\IMG_0001.JPG
PSParentPath      : Microsoft.PowerShell.Core\FileSystem::C:\
PSChildName       : IMG_0001.JPG
PSDrive           : C
PSProvider        : Microsoft.PowerShell.Core\FileSystem
Mode              : -a----
VersionInfo       : File:             C:\IMG_0001.JPG
                    InternalName:
                    OriginalFilename:
                    FileVersion:
                    FileDescription:
                    Product:
                    ProductVersion:
                    Debug:            False
                    Patched:          False
                    PreRelease:       False
                    PrivateBuild:     False
                    SpecialBuild:     False
                    Language:

BaseName          : IMG_0001
Target            : {}
LinkType          :
Name              : IMG_0001.JPG
Length            : 8747721
DirectoryName     : C:\
Directory         : C:\
IsReadOnly        : False
Exists            : True
FullName          : C:\IMG_0001.JPG
Extension         : .JPG
CreationTime      : 2016/11/29 23:17:34
CreationTimeUtc   : 2016/11/29 14:17:34
LastAccessTime    : 2016/11/29 23:17:34
LastAccessTimeUtc : 2016/11/29 14:17:34
LastWriteTime     : 2016/11/29 21:47:40
LastWriteTimeUtc  : 2016/11/29 12:47:40
Attributes        : Archive

2.

GetDetailsOfは、ファイルプロパティの詳細情報のID番号を指定して情報を取得します。
先ずは、GetDetailsOfを使い詳細情報のIDと項目名を列挙して必要なID番号を見つけます。
$path = "C:\IMG_0001.JPG"

$shell = New-Object -COMObject Shell.Application

$folder = Split-Path $path
$file = Split-Path $path -Leaf

$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)

0..310 | Foreach-Object { '{0}:{1}' -f $_, $shellfolder.GetDetailsOf($null, $_) }
結果: 求めるカメラ機器のモデル名が保存されているプロパティは30番であると判明しました。
次に求める、Exifの撮影日時に関する情報は12番の撮影日時に反映されているハズです。
それでは、特定したID番号を指定してGetDetailsOfで情報をとります。
0:名前
  1:サイズ
  2:項目の種類
  3:更新日時
  4:作成日時
  5:アクセス日時
  6:属性
  7:オフラインの状態
  8:利用可能性
  9:認識された種類
 10:所有者
 11:分類
 12:撮影日時
 13:参加アーティスト
 14:アルバム
 15:年
 16:ジャンル
 17:指揮者
 18:タグ
 19:評価
 20:作成者
 21:タイトル
 22:件名
 23:分類項目
 24:コメント
 25:著作権
 26:トラック番号
 27:長さ
 28:ビット レート
 29:保護
 30:カメラのモデル
 31:大きさ
 32:カメラの製造元
 33:会社
 34:ファイルの説明
 35:プログラム名
 36:継続時間
 37:オンライン
 38:再帰
 39:場所
 40:任意出席者アドレス
 41:任意出席者
 42:開催者住所
 43:開催者名
 44:アラーム時刻
 45:必須出席者アドレス
 46:必須出席者
 47:リソース
 48:会議の状態
 49:空き時間情報
 50:合計サイズ
 51:アカウント名
 52:
 53:進捗状況
 54:コンピューター
 55:記念日
 56:秘書の名前
 57:秘書の電話
 58:誕生日
 59:住所 (会社)
 60:市 (会社)
 61:国/地域 (会社)
 62:私書箱 (会社)
 63:郵便番号 (会社)
 64:都道府県 (会社)
 65:番地 (会社)
 66:FAX 番号 (会社)
 67:会社のホーム ページ
 68:会社電話
 69:コールバック番号
 70:自動車電話
 71:子供
 72:会社代表電話
 73:部署
 74:電子メール アドレス
 75:電子メール2
 76:電子メール3
 77:電子メールの一覧
 78:電子メール表示名
 79:表題2
 80:名
 81:氏名
 82:性別
 83:名2
 84:趣味
 85:住所 (自宅)
 86:市 (自宅)
 87:国/地域 (自宅)
 88:私書箱 (自宅)
 89:郵便番号 (自宅)
 90:都道府県 (自宅)
 91:番地 (自宅)
 92:自宅 FAX
 93:自宅電話
 94:IM アドレス
 95:イニシャル
 96:役職
 97:ラベル
 98:姓
 99:住所 (郵送先)
100:ミドル ネーム
101:携帯電話
102:ニックネーム
103:勤務先所在地
104:住所 (その他)
105:ほかの市区町村
106:他の国/地域
107:他の私書箱
108:他の郵便番号
109:他の都道府県
110:他の番地
111:ポケットベル
112:肩書き
113:市区町村 (郵送先)
114:国/地域
115:私書箱 (郵送先)
116:郵便番号 (郵送先)
117:都道府県
118:番地 (郵送先)
119:プライマリ電子メール
120:通常の電話
121:職業
122:配偶者
123:サフィックス
124:TTY/TTD 電話
125:テレックス
126:Web ページ
127:内容の状態
128:内容の種類
129:取得日時
130:アーカイブ日時
131:完了日
132:デバイス カテゴリ
133:接続済み
134:探索方法
135:フレンドリ名
136:ローカル コンピュー
137:製造元
138:モデル
139:ペアリング済み
140:クラス
141:状態
142:状態
143:クライアント ID
144:共同作成者
145:コンテンツの作成日時
146:前回印刷日
147:前回保存日時
148:事業部
149:ドキュメント ID
150:ページ数
151:スライド
152:総編集時間
153:単語数
154:期限
155:終了日
156:ファイル数
157:ファイル拡張子
158:ファイル名
159:ファイル バージョン
160:フラグの色
161:フラグの状態
162:空き領域
163:
164:
165:グループ
166:共有の種類
167:ビットの深さ
168:水平方向の解像度
169:幅
170:垂直方向の解像度
171:高さ
172:重要度
173:添付
174:削除
175:暗号化の状態
176:フラグの有無
177:終了済
178:未完了
179:開封の状態
180:共有
181:製作者
182:日付時刻
183:フォルダー名
184:フォルダーのパス
185:フォルダー
186:参加者
187:パス
188:場所ごと
189:種類
190:連絡先の名
191:履歴の種類
192:言語
193:最終表示日
194:説明
195:リンクの状態
196:リンク先
197:URL
198:
199:
200:
201:メディアの作成日時
202:リリース日
203:エンコード方式
204:エピソード番号
205:プロデューサー
206:発行元
207:シーズン番号
208:サブタイトル
209:ユーザー Web URL
210:作者
211:
212:添付ファイル
213:BCC アドレス
214:BCC
215:CC アドレス
216:CC
217:会話 ID
218:受信日時
219:送信日時
220:送信元アドレス
221:差出人
222:添付ファイルの有無
223:送信者アドレス
224:送信者名
225:ストア
226:送信先アドレス
227:To do タイトル
228:宛先
229:経費情報
230:アルバムのアーティス
231:アルバム アーティス
232:アルバム ID
233:アルバムで並べ替え
234:参加アーティストで並
235:ビート数/分
236:作曲者
237:作曲者で並べ替え
238:ディスク
239:イニシャル キー
240:コンパイルの一部
241:雰囲気
242:セットのパート
243:期間
244:色
245:保護者による制限
246:保護者による制限の理
247:使用領域
248:EXIF バージョン
249:イベント
250:露出補正
251:露出プログラム
252:露出時間
253:絞り値
254:フラッシュ モード
255:焦点距離
256:35mm 焦点距離
257:ISO 速度
258:レンズ メーカー
259:レンズ モデル
260:光源
261:最大絞り
262:測光モード
263:向き
264:人物
265:プログラムのモード
266:彩度
267:対象の距離
268:ホワイト バランス
269:優先度
270:プロジェクト
271:チャンネル番号
272:この回のタイトル
273:字幕
274:再放映
275:SAP
276:放送日
277:プログラムの説明
278:記録時間
279:ステーション コール
280:局名
281:概要
282:抜粋
283:自動要約
284:関連度
285:ファイルの所有権
286:秘密度
287:共有ユーザー
288:共有状態
289:
290:製品名
291:製品バージョン
292:サポートのリンク
293:ソース
294:開始日
295:共有中
296:同期状況
297:課金情報
298:完了
299:仕事の所有者
300:タイトルで並べ替え
301:総ファイル サイズ
302:商標
303:ビデオ圧縮
304:ディレクター
305:データ速度
306:フレーム高
307:フレーム率
308:フレーム幅
309:ビデオの向き
310:総ビット レート

3.

GetDetailsOfを使いIDが30番と12番の詳細情報を取得します。
$path = "C:\IMG_0001.JPG"

$shell = New-Object -COMObject Shell.Application

$folder = Split-Path $path
$file = Split-Path $path -Leaf

$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)

$shellfolder.GetDetailsOf($shellfile, 30) 
$shellfolder.GetDetailsOf($shellfile, 12) 
結果: ファイルプロパティの詳細情報からカメラのモデル名は取得できましたが、撮影日時はなにも表示されません。
確認のため、GetDetailsOfを使いID番号と詳細情報を列挙してみます。前出の列挙は項目名です。
Nikon COOLSCAN III LS-30
 

4.

では、GetDetailsOfを使いID番号と詳細情報を列挙してみます。
# ファイルプロパティの詳細情報の取得し列挙する

# ファイルのフルパス
$path = "C:\IMG_0001.jpg"

# フルパスを分割
$folder = Split-Path $path
$file = Split-Path $path -Leaf
#Write-Host ディレクトリーパス: $folder"`r`n"ファイル名: $file

# シェルオブジェクトを作成
$shell = New-Object -ComObject Shell.Application

# フォルダの指定
$shellFolder = $shell.NameSpace($folder)

# ファイルの指定
$shellFile = $shellFolder.parseName($file)

# 詳細プロパティの要約 -1を指定
Write-Host $shellFolder.GetDetailsOf($shellFile,-1)

# 詳細プロパティを列挙 とりあえず310項目
for ($i=0; $i -lt 310; $i++){
    Write-Host $i = $shellFolder.GetDetailsOf($shellFile,$i)
}
結果: 12の撮影日時には情報はありませんでしたので、ファイルのExif情報から撮影日情報を取得してみます。
対象の画像は、2001年製のフィルムスキャナー「Nikon COOLSCAN III LS-30」でスキャンされているので、撮影日時に反映される項目が設定されていない可能性があります。
Exif情報は、詳細情報とは別に記録されています。
項目の種類: JPG ファイル
評価: 評価なし
大きさ: ‪3894 x 2592‬
サイズ: 8.34 MB

0 = IMG_0001.jpg
1 = 8.34 MB
2 = JPG ファイル
3 = 2016/11/29 21:47
4 = 2016/11/29 23:17
5 = 2016/11/29 23:17
6 = A
7 =
8 = オフラインで利用可能
9 = イメージ
10 = Administrators
11 = ピクチャ
12 =
13 =
14 =
15 =
16 =
17 =
18 =
19 = 評価なし
20 =
21 =
22 =
23 =
24 =
25 =
26 =
27 =
28 =
29 =
30 = COOLSCAN III LS-30
31 = ‪3894 x 2592‬
32 = Nikon
33 =
34 =
35 =
36 =
37 =
38 =
39 =
40 =
41 =
42 =
43 =
44 =
45 =
46 =
47 =
48 =
49 =
50 = 110 GB
51 =
52 =
53 =
54 = DESKTOP-******* (この PC)
55 =
56 =
57 =
58 =
59 =
60 =
61 =
62 =
63 =
64 =
65 =
66 =
67 =
68 =
69 =
70 =
71 =
72 =
73 =
74 =
75 =
76 =
77 =
78 =
79 =
80 =
81 =
82 =
83 =
84 =
85 =
86 =
87 =
88 =
89 =
90 =
91 =
92 =
93 =
94 =
95 =
96 =
97 =
98 =
99 =
100 =
101 =
102 =
103 =
104 =
105 =
106 =
107 =
108 =
109 =
110 =
111 =
112 =
113 =
114 =
115 =
116 =
117 =
118 =
119 =
120 =
121 =
122 =
123 =
124 =
125 =
126 =
127 =
128 =
129 =
130 =
131 =
132 =
133 =
134 =
135 =
136 =
137 =
138 =
139 =
140 =
141 =
142 =
143 =
144 =
145 =
146 =
147 =
148 =
149 =
150 =
151 =
152 =
153 =
154 =
155 =
156 =
157 = .jpg
158 = IMG_0001.jpg
159 =
160 =
161 =
162 = 57.1 GB
163 =
164 =
165 =
166 =
167 = 24
168 = ‎2700 dpi
169 = ‎3894 ピクセル
170 = ‎2700 dpi
171 = ‎2592 ピクセル
172 =
173 =
174 =
175 =
176 =
177 =
178 =
179 =
180 = いいえ
181 =
182 =
183 = C:\
184 = C:\
185 = C:\
186 =
187 = C:\IMG_0001.jpg
188 =
189 = JPG ファイル
190 =
191 =
192 =
193 =
194 =
195 = 未解決
196 =
197 =
198 =
199 =
200 =
201 =
202 =
203 =
204 =
205 =
206 =
207 =
208 =
209 =
210 =
211 =
212 =
213 =
214 =
215 =
216 =
217 =
218 =
219 =
220 =
221 =
222 =
223 =
224 =
225 =
226 =
227 =
228 =
229 =
230 =
231 =
232 =
233 =
234 =
235 =
236 =
237 =
238 =
239 =
240 =
241 =
242 =
243 =
244 =
245 =
246 =
247 = ‎48%
248 = 0210
249 =
250 =
251 =
252 =
253 =
254 =
255 =
256 =
257 =
258 =
259 =
260 =
261 =
262 =
263 =
264 =
265 =
266 =
267 =
268 =
269 =
270 =
271 =
272 =
273 =
274 =
275 =
276 =
277 =
278 =
279 =
280 =
281 =
282 =
283 =
284 =
285 =
286 =
287 =
288 = 非共有
289 = 利用可能
290 =
291 =
292 =
293 =
294 =
295 =
296 =
297 =
298 =
299 =
300 =
301 =
302 =
303 =
304 =
305 =
306 =
307 =
308 =
309 =

5.

Exif情報を取得するには.NET FrameworkのSystem.Drawing.BitmapクラスからPropertyItemsを使う必要があります。
PropertyItemsで抽出する情報もID番号を指定する必要があるので、Exif情報の一覧表で必要とする項目のあたりを付けます。


6.

とりあえず、画像が持つExif情報を列挙してみる。
求める撮影日時的な情報が有ればIDから項目が何であるかを調べます。
$path = "C:\IMG_0001.JPG"

# アセンブリの読み込み
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# 画像を指定します。
$image = New-Object System.Drawing.Bitmap ($path)

# IDと情報を列挙します
foreach ($item in $image.PropertyItems) {
    # バイナリで格納されているのでText.Encoding.ASCIIのGetString関数で文字列にします
    $exifv = [System.Text.Encoding]::ASCII.GetString($item.Value)
    # 表示します
    Write-Host $item.id = $exifv # プロンプトに表示
}

# オブジェクトの破棄
$image.Dispose()
結果: 画像が持つExif情報の一覧から、必要な撮影日時の情報は306番にあることがわかりましたので、次で情報を抽出してみます。
271 = Nikon
272 = COOLSCAN III LS-30
282 = ?
   
283 = ?
   
296 =  
306 = 2001.10.25 20.45.27
531 =  
36864 = 0210
37121 =    
37500 =
40960 = 0100
40961 =  
40962 = 6 
40963 =

20625 =                                                                                                                
20624 =                                                                                                                
34675 =    ?NKON    mntrRGB XYZ ?      ;  acspAPPL    none                  ??      ?-
desc   ?   MrXYZ   @    gXYZ   T    bXYZ   h    rTRC   |    gTRC   ?    bTRC   ?    wtpt   ?    cprt   ?   ,desc       i
kon Adobe RGB 4.0.0.3000           ikon Adobe RGB 4.0.0.3000    XYZ       ?   O?   ?XYZ       4?  ?+   ?XYZ       &2   
??curv         3  curv         3  curv         3  XYZ       ?T       ?text    Nikon Inc. & Nikon Corporation 2001

7.

PropertyItemsでExif情報からID30を抽出します。
$path = "C:\IMG_0001.JPG"

# アセンブリの読み込み
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# 画像を指定します。
$image = New-Object System.Drawing.Bitmap ($path)

# 求めるIDを抽出
foreach ($item in $image.PropertyItems) {
    if ($item.Id -eq 306) {
        $exif_ModifyDate = [System.Text.Encoding]::ASCII.GetString($item.Value)
        Write-Host $item.id = $exif_ModifyDate
    }
}

# オブジェクトの破棄
$image.Dispose()
結果: 撮影日時として使える情報が取得できました。
306 = 2016.11.25 20.45.27

8.

あとがき


例示の画像はスキャン画像なのでExif情報の撮影日時的な項目を、ファイルプロパティに当て込むのは編なので、適当な項目にメモとして流し込むのがよさそうです。

今回取得した情報は、Set-ItemPropertyでPowershellで扱えるGet-ItemPropertやGet-ChildItemを使い取得できるFileInfoプロパティ(-membertype property)に代入することができます。

また、Exif情報を取得する時に利用した.NET FrameworkのSystem.Drawingクラスを使えば、画像にテキストとしてドローすることも可能です。

ここまでは、素のままのPowershellで行うことができます。私の環境、windows10 64bit Proと windows10 32bit Homeで動作を確認しました。

ファイルプロパティの詳細情報の編集や追加、Exif情報の編集や追加は素のPowershellでは難しそうですが、外部のモジュールなどを組み込むとできるかもしれません。

以上

このブログの人気の投稿

DOMノードオブジェクトを文字列に変換する

PowerShellで複数ファイルのプロパティを取得する方法(準備編)

Powershell: プロパティの詳細情報インデックスと項目名の列挙

簡単 YouTube動画をダウンロード、音声のみ保存する方法 2019

書字方向 横書方向変換スクリプト 左書きから右書きへ(コピペ用途)

Blender: 辺の長さを数値で指定するアドオン