Erweiterte Dateieigenschaften (extended properties)

Veröffentliche deine funktionierenden Skripte und Funktionen

Moderator: jNizM

just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Erweiterte Dateieigenschaften (extended properties)

06 Oct 2020, 05:33

Moin,

wegen des Beitrags mit dem sprechenden Namen Typenkonflikt (Präsidentschaftsdebattenfrei) habe ich mich wieder einmal mit den 'erweiterten Dateieigenschaften' beschäftigt. Ich habe dabei u.a. von SKAN's Beitrag Filexpro() : File Extended Properties Object profitiert.

Herausgekommen sind zwei Funktionen, die bestimmte Dateieigenschaften extrahieren. Ich stelle die Funktionen in die folgenden zwei Beiträge, damit sie nicht allzu schnell im Nirvana der Hilfeforen verschwinden.

Beide Funktionen sollen nur als Beispiele dienen und müssen für den produktiven Einsatz wahrscheinlich angepasst werden.
Last edited by just me on 06 Oct 2020, 05:41, edited 1 time in total.
just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Erweiterte Dateieigenschaften (extended properties)

06 Oct 2020, 05:34

GetGpsData()

Die Funktion versucht, in eine Datei eingebettete GPS-Informationen auszulesen. Sie gibt ein assoziatives Array zurück, das als Schlüssel den (englischen) Eigenschaftsnamen und den/die zugehörigen Wert/e enthält. Schlüssel, die keine Werte liefern, werden nicht ins Array übernommen.

Code: Select all

#NoEnv
SetBatchLines, -1
SetWorkingDir, %A_ScriptDir%
FilePath := "20170115015626-f6b39ecb.jpg" ; <<<<<<<<<<<<<<<<<<<<<<<< anpassen
Props := GetGpsData(FilePath)
Msg := ""
For PropName, PropValue In Props
   Msg .= PropName . " = " . PropValue . "`n"
MsgBox, 0, %FilePath%, %Msg%
ExitApp

GetGpsData(FilePath) {
   Local
   ; Namespace: "System.GPS."
   Static GpsProps := ["Altitude"
                     , "AltitudeDenominator"
                     , "AltitudeNumerator"
                     , "AltitudeRef"
                     , "AreaInformation"
                     , "Date"
                     , "DestBearing"
                     , "DestBearingDenominator"
                     , "DestBearingNumerator"
                     , "DestBearingRef"
                     , "DestDistance"
                     , "DestDistanceDenominator"
                     , "DestDistanceNumerator"
                     , "DestDistanceRef"
                     , "DestLatitude"
                     , "DestLatitudeDenominator"
                     , "DestLatitudeNumerator"
                     , "DestLatitudeRef"
                     , "DestLongitude"
                     , "DestLongitudeDenominator"
                     , "DestLongitudeNumerator"
                     , "DestLongitudeRef"
                     , "Differential"
                     , "DOP"
                     , "DOPDenominator"
                     , "DOPNumerator"
                     , "ImgDirection"
                     , "ImgDirectionDenominator"
                     , "ImgDirectionNumerator"
                     , "ImgDirectionRef"
                     , "Latitude"
                     , "LatitudeDecimal"
                     , "LatitudeDenominator"
                     , "LatitudeNumerator"
                     , "LatitudeRef"
                     , "Longitude"
                     , "LongitudeDecimal"
                     , "LongitudeDenominator"
                     , "LongitudeNumerator"
                     , "LongitudeRef"
                     , "MapDatum"
                     , "MeasureMode"
                     , "ProcessingMethod"
                     , "Satellites"
                     , "Speed"
                     , "SpeedDenominator"
                     , "SpeedNumerator"
                     , "SpeedRef"
                     , "Status"
                     , "Track"
                     , "TrackDenominator"
                     , "TrackNumerator"
                     , "TrackRef"
                     , "VersionID"]
   SplitPath, FilePath, FileName , FileDir
   If (FileDir = "")
      FileDir := A_WorkingDir
   Props := {}
   If (SFI := ComObjCreate("Shell.Application").NameSpace(FileDir).ParseName(FileName)) {
      For Each, PropName In GpsProps {
         PropVal := SFI.ExtendedProperty("System.GPS." . PropName)
         If IsObject(PropVal) {
            If (ComObjType(PropVal) & 0x2000) { ; VT_ARRAY
               Values := ""
               For Value In PropVal
                  Values .= Value . ", "
               Props[PropName] := RTrim(Values, ", ")
            }
         }
         Else If (PropVal <> "")
            Props[PropName] := PropVal
      }
   }
   Return Props
}
Last edited by just me on 06 Oct 2020, 05:40, edited 1 time in total.
just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Erweiterte Dateieigenschaften (extended properties)

06 Oct 2020, 05:34

GetFullDetails()

Die Funktion ist entstanden, als ich über die PropList Eigenschaft gestolpert bin. Sie versucht, sämtliche Eigenschaften auszulesen, die im Reiter Details der Dateieigenschaften gelistet werden. Das resultierende Array enthält Objekte mit den Schlüsseln N (Name) und V (Wert/e) der gefundenen Eigenschaften. Wie bei GetGpsData() werden Schlüssel, die keine Werte liefern, nicht ins Array übernommen.

Während des Tests hatte ich Abstürze beim Zugriff auf die Eigenschaft System.SharedWith (Freigegeben für) und habe sie deshalb in das Array Exclude aufgenommen. Damit werden Leseversuche unterbunden.

Code: Select all

#NoEnv
SetWorkingDir, %A_ScriptDir%
#NoEnv
SetBatchLines, -1
FilePath := "20170115015626-f6b39ecb.jpg"
Props := GetFullDetails(FilePath)
Gui, Add, ListView, w600 r20, PropName|PropValue
For Each, Prop In Props
   LV_Add("", Prop.N, Prop.V)
LV_ModifyCol()
Gui, Show, , GetFullDetails
Return
GuiClose:
ExitApp

GetFullDetails(FilePath) {
   ; The properties in 'Exclude' caused problems during my tests
   Static Exclude := {"System.SharedWith": 1}
   SplitPath, FilePath, FileName , FileDir
   If (FileDir = "")
      FileDir := A_WorkingDir
   Props := {}
   If (SFI := ComObjCreate("Shell.Application").NameSpace(FileDir).ParseName(FileName)) {
      PropList := SFI.ExtendedProperty("System.PropList.FullDetails")
      If (SubStr(PropList, 1, 5) = "prop:") {
         Props := {}
         PropCount := 0
         For Each, PropName In StrSplit(SubStr(PropList, 6), ";", "*") {
            If Exclude.HasKey(PropName)
               Continue
            If InStr(PropName, ".PropGroup.") {
               PropName := ">>>>> " . StrSplit(PropName, ".")[3] . " <<<<<"
               Props[++PropCount] := {N: PropName, V: ""}
               Continue
            }
            PropVal := SFI.ExtendedProperty(PropName)
            If IsObject(PropVal) {
               If (ComObjType(PropVal) & 0x2000) { ; VT_ARRAY
                  Values := ""
                  For Value In PropVal
                     Values .= Value . ", "
                  Props[++PropCount] := {N: PropName, V: RTrim(Values, ", ")}
               }
            }
            Else If (PropVal <> "") {
               Props[++PropCount] := {N: PropName, V: PropVal}
            }
         }
      }
   }
   Return Props
}
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Erweiterte Dateieigenschaften (extended properties)

06 Oct 2020, 10:27

Danke fürs 'sharen' :thumbup: (Danksagung von Shaun (dem Schaf) nach Ganzkörperrasur)
Mir stellt sich noch die Frage, ob es für jeden Dateityp anzahlmäßig unterschiedliche Sätze an 'default'-Eigenschaften gibt (beide Funktionen skippen ja etwaige vorhandene 'Leerfelder'), und ob das irgendwo dokumentiert ist?
Eine Problemstellung wäre es z.B. fehlende Einträge für einen Dateityp zu ermitteln um diese ggf zu ergänzen.

Als Denkansatz habe ich mal für die Liste aller Datei-assingments (Stichwort: assoc) auf einer Box jeweils die erste Datei ge-parsed, nach type/art kategorisiert und die Anzahl der props gezählt. Wie gesagt, das System unterscheidet scheints Dateiformate nach verschiedenen Typen/Arten die da wären: music/video/system/document/text/...

:)
halweg
Posts: 93
Joined: 17 Apr 2018, 10:34
Location: Dresden

Re: Erweiterte Dateieigenschaften (extended properties)

07 Oct 2020, 05:16

Danke auch meinerseits. Hab's gerade probiert, offensichtlich kann man so sehr einfach auf die Dateimerkmale zugreifen. Ich verstehe zwar nicht alles, was den Objektzugriff angeht, aber das muss man wohl auch nicht.
just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Erweiterte Dateieigenschaften (extended properties)

07 Oct 2020, 05:32

Moin @halweg,

meinst Du das?

Code: Select all

	If IsObject(PropVal) {
just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Erweiterte Dateieigenschaften (extended properties)

07 Oct 2020, 05:34

Moin @BoBo,

etwa so?

GetFullDetailsNames()

Code: Select all

#NoEnv
SetWorkingDir, %A_ScriptDir%
#NoEnv
SetBatchLines, -1
FilePath := "20170115015626-f6b39ecb.jpg"
Props := GetFullDetailsNames(FilePath)
Gui, Add, ListView, w600 r20, #|PropName
For Index, PropName In Props
   LV_Add("", Index, PropName)
LV_ModifyCol()
Gui, Show, , GetFullDetails
Return
GuiClose:
ExitApp

GetFullDetailsNames(FilePath) {
   SplitPath, FilePath, FileName , FileDir
   If (FileDir = "")
      FileDir := A_WorkingDir
   If (SFI := ComObjCreate("Shell.Application").NameSpace(FileDir).ParseName(FileName)) {
      PropList := SFI.ExtendedProperty("System.PropList.FullDetails")
      If (SubStr(PropList, 1, 5) = "prop:") {
         Props := {}
         For Each, PropName In StrSplit(SubStr(PropList, 6), ";")
            Props[A_Index] := InStr(PropName, ".PropGroup.") ? ">>>>> " . PropName . " <<<<<" : PropName
      }
   }
   Return Props
}
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Erweiterte Dateieigenschaften (extended properties)

07 Oct 2020, 08:01

Sieht sehr vielversprechend aus, wobei ich noch nicht ganz raushabe warum die Prop.Groups anteilig 'Sortenunrein' gemischt werden z.B. mit parsen einer MP4 findet sich in group Video > Media prop(s), und in group Media > Music (props)? Gehe jedoch davon aus das dies Systembedingt ist??
Ergo, Amen :) Danke.
halweg
Posts: 93
Joined: 17 Apr 2018, 10:34
Location: Dresden

Re: Erweiterte Dateieigenschaften (extended properties)

07 Oct 2020, 08:49

just me wrote:
07 Oct 2020, 05:32
meinst Du das?

Code: Select all

	If IsObject(PropVal) {
Für mich ist die Arbeit mit Objekten in AHK ganz allgemein noch Neuland und mir fehlt die Routine, auch um fremden Code in diesem Bereich leicht zu verstehen.
just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Erweiterte Dateieigenschaften (extended properties)

08 Oct 2020, 07:03

BoBo wrote:
07 Oct 2020, 08:01
... Gehe jedoch davon aus das dies Systembedingt ist?? ...
Es ist jedenfalls das, was vom System geliefert und nach meinen Stichproben in Details aufgelistet ist. Man kann den Namen dort ja nicht entnehmen, welcher Untergruppe der Wert intern zugeordnet ist. Wahrscheinlich hat Microsoft im Laufe der Jahre irgendwann einmal bemerkt, dass sich die ursprünglich gewählte interne Einteilung nicht (immer) aufrechterhalten lässt.
just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Erweiterte Dateieigenschaften (extended properties)

08 Oct 2020, 07:27

halweg wrote:
07 Oct 2020, 08:49
... Für mich ist die Arbeit mit Objekten in AHK ganz allgemein noch Neuland und mir fehlt die Routine, auch um fremden Code in diesem Bereich leicht zu verstehen.
Bei den Skripten gibt es zwei Arten von Objekten, zunächst einmal die COM-Objekte, die von den COM-AUfrufen zurückgegeben werden, und dann noch die intern aufgebauten AHK-Objekte.
  • COM:
    Mit COM kommt AHK inzwischen recht gut zurecht. SFI (ShellFolderItem) verfügt u.a. über die Methode ExtendedProperty, die für einen übergebenen Eigenschaftsnamen den Wert der Eigenschaft zurückgibt, so vorhanden. Bei einfachen Werttypen wie Zahlen oder Zeichenketten übernimmt AHK die Umwandlung in ein für AHK direkt handhabbares Format. Bei den GPS-Daten werden aber auch COM-SafeArrays zurückgegeben. AHK kennt sich damit immerhin soweit aus, dass man die Werte mit For-Schleifen auslesen kann. Deshalb gibt es im Skript die Abfrage IsObject() und die anschließende Prüfung des Typs.
  • AHK:
    Das sind in diesem Fall recht 'einfache' Objekte. Im Fall von GetGpsData() ist es ein assoziatives Array, in dem den Eigenschaftsnamen (Key) die Eigenschaftswerte (Value) direkt zugeordnet sind.
    Bei GetFullDetails() wird ein sogenanntes 'einfaches' Array mit fortlaufendem Index erstellt, unter dem jeweils ein Objekt (assoziatives Array) abgelegt ist. Dieses Objekt enthält die zwei Schlüssel N mit dem Namen und V mit dem Wert der Eigenschaft. Dieses Konstrukt habe ich gewählt, um die vorgegebene Reihenfolge der Eigenschaften beibehalten zu können.
halweg
Posts: 93
Joined: 17 Apr 2018, 10:34
Location: Dresden

Re: Erweiterte Dateieigenschaften (extended properties)

15 Oct 2020, 08:38

Danke noch mal just me für die Erläuterung zum Thema Objekte. Letztlich war das ja auch die Hemmschwelle und so stieg ich erst Anfang dieses Jahres auf AHK 1.1 um und nutze nun endlich wieder die aktuelle Version.

Inzwischen lerne ich auch, dass die "einfachen Objekte", wie z. B. die assoziativen Arrays, Dinge ermöglichen, um die ich lange herumprogrammieren musste.
Trotzdem bin ich, zumindest hinsichtlich der externen COM Objekte, noch sehr zurückhaltend. Denn diese erweitern meinen AHK Code um fremde Konstrukte. Was ich damit tun und lassen kann, finde ich hier nicht einfach über F1- Hilfe oder über den Objektexplorer, so wie ich das z. B. bei VBA gewöhnt bin. Während mir also z. B. AHK per WINGETTITLE den Titel eines Windows Fensters auswirft und ich dazu nur diesen Befehl kennen muss, brauche ich für SFI einen guten Einblick in fremde Objektstrukturen, eine zweite Dokumentation oder mindestens eine Anregung hier im Forum.

Gleichzeitig weiß ich, dass ich über solche Objekte einige meiner kniffligsten Probleme einfacher lösen könnte, z. B. die Übergabe von Variablen von AHK an VBA (außerhalb der Zwischenablage), das Auslesen der aktuellen Adresse und weiterer Daten aus Firefox-Fenstern oder die Ansteuerung eines Acrobat Reader Fensters. So gesehen also danke fürs Mutmachen!

Viele Grüße, Halweg
fredchf
Posts: 54
Joined: 30 Sep 2013, 14:55

Re: Erweiterte Dateieigenschaften (extended properties)

23 Nov 2020, 08:00

Das sieht sehr nützlich aus, ich suchte schon mal einen Weg den letzten Bearbeiter von Office-Dokumenten zu ermitteln. Das scheint hiermit ein Kinderspiel, vielen Dank

Return to “Skripte und Funktionen”

Who is online

Users browsing this forum: No registered users and 3 guests