Retrieving Extended File Properties

topic: 

When you right-click a file in Windows Explorer and select Properties from the shortcut menu, a dialog box displays basic properties for that file, including such things as file name, file size, and the file creation, last access, and last modification dates. In addition to these basic properties, the Windows operating system also tracks a number of extended file properties. These properties are typically hidden; to display them in Windows Explorer, you must click View, click Choose Details, and then select the desired properties from the resulting dialog box.

The Shell Folder object includes a GetDetailsOf method that allows to access these extended properties. A ParseName method

can be used to retrieve a FolderItem object that represents a specified item.

$SAMPLECODE$

 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
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
CLEAR

#DEFINE ccPropName  1
#DEFINE ccPropIndex 2
#DEFINE ccPropValue 3
lcCRLF = CHR(13) + CHR(10)

loShell = CREATEOBJECT("Shell.Application")
 
DIMENSION laFileProperties[1,3]
lnPropCount = 0

lcFolderName = "C:\Windows"
loFolder = loShell.Namespace(lcFolderName)

* Enumerate available properties by passing Null as the first parameter to the GetDetailsOf() method
FOR i = 0 TO 99
	lcPropName = loFolder.GetDetailsOf(Null, i)

	IF EMPTY(lcPropName)
		* Ignore empty items. They're either reserved or not supported for the current folder.
		LOOP
	ENDIF	
	
	* One property 
	lnPropCount = lnPropCount + 1 
	DIMENSION laFileProperties[lnPropCount, ALEN(laFileProperties,2)]
	* Property name
	laFileProperties[lnPropCount,ccPropName] = lcPropName 
	* Property index for the GetDetailsOf() method
	laFileProperties[lnPropCount,ccPropIndex] = i
ENDFOR

* Special 'Info Tip' ptoperty with index -1
lnPropCount = lnPropCount + 1 
DIMENSION laFileProperties[lnPropCount, ALEN(laFileProperties,2)] 
laFileProperties[lnPropCount,ccPropName] = "Info Tip" 
laFileProperties[lnPropCount,ccPropIndex] = -1

*------------------------------------------------------------------------------------------------------
* Retrieve extended properties for a particular file and store its values in the same array (column 3)
*	and convert properties into cursor's fields through XmlToCursor()
lcFileName = "clock.avi"
loFolder = loShell.Namespace(lcFolderName)
* Get reference to the file 
loFile = loFolder.ParseName(lcFileName)
* Check if file exists and retreive property values
IF NOT ISNULL(loFile)
	lcXml = [<!--?xml version = "1.0" encoding="Windows-1252" standalone="yes"?--><vfpdata>]
	lcXml = lcXml + lcCRLF + "<fileproperties>"
	FOR lnInd=1 TO lnPropCount 
		lvValue = loFolder.GetDetailsOf(loFile, laFileProperties[lnInd, ccPropIndex])
		laFileProperties[lnInd, ccPropValue] = lvValue 
		lcFieldName = CHRTRAN(laFileProperties[lnInd, ccPropName], SPACE(1), "")
		lcXml = lcXml + lcCRLF + TEXTMERGE("<{{lcFieldName}}>{{lvValue}}<!--{{lcFieldName}}--> ",.F.,"{{", "}}" ) 
	ENDFOR
	lcXml = lcXml + lcCRLF + "</fileproperties>"
	lcXml = lcXml + "</vfpdata>"
ENDIF

XMLTOCURSOR(lcXML, "crsFilePropertiesEx")

BROWSE LAST NOWAIT 

*------------------------------------------------------------------------------------------------------
* Retrieve extended properties for a list of files in the same folder

loFolder = loShell.Namespace(lcFolderName)
lcXml = [<!--?xml version = "1.0" encoding="Windows-1252" standalone="yes"?--><vfpdata>]

FOR EACH loItem IN loFolder.Items 

	IF INLIST(UPPER(JUSTEXT(loItem.Name)), "AVI", "BMP")
		lcXml = lcXml + lcCRLF + "<fileproperties>"
		FOR lnInd=1 TO lnPropCount 
			lvValue = loFolder.GetDetailsOf(loItem, laFileProperties[lnInd, ccPropIndex])
			laFileProperties[lnInd, ccPropValue] = lvValue 
			lcFieldName = CHRTRAN(laFileProperties[lnInd, ccPropName], SPACE(1), "")
			lcXml = lcXml + lcCRLF + TEXTMERGE("<{{lcFieldName}}>{{lvValue}}<!--{{lcFieldName}}--> ",.F.,"{{", "}}" ) 
		ENDFOR
		lcXml = lcXml + lcCRLF + "</fileproperties>"
	ENDIF	
ENDFOR

lcXml = lcXml + "</vfpdata>"

XMLTOCURSOR(lcXML, "crsFilesPropertiesEx")

BROWSE LAST NOWAIT 

RETURN

Comments

Whilst this is a good snippet, the problem I have is that I want to retrieve the GPS EXIF tags from a JPG image using Visual FoxPro.
I don't think anyone has done this in VFP before although there are plenty of viewers written in C++. I want mine in VFP - So any thoughts would be useful.

Hi John,

Apparently it has been done in VFP already <a href="http://www.news2news.com/vfp/?example=461">GDI+: reading and writing metadata in JPEG and TIFF files </a>. Check also <a href="http://www.codeplex.com/wikipage?ProjectName=VFPX&title=GDIPlusX">GdiPlusX</a>.