Dateieigenschaften ermitteln

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

In Access-Datenbanken werden ja nicht immer nur Personen, Objekte und Vorgänge verwaltet. Nicht selten lesen Sie auch Dateien und deren Eigenschaften in Tabellen ein. Denken Sie etwa an die Informationen, die Sie Audio- oder Videodateien für eine Medienverwaltung abringen möchten. Mit dem Rüstzeug von VBA allein kommen Sie hier nicht weit, wohl aber mit den Shell-Objekten von Windows.

Dateieigenschaften im Explorer

Der Explorer von Windows zeigt einige Eigenschaften von Dateien in voreingestellten Spalten an, wenn Sie die Detailansicht auswählen. Welche das sind, hängt vom Ordnerinhalt ab, den Windows vermutet. Für allgemeine Dateien sind das neben dem Namen in der Regel noch der Dateityp, die Größe, sowie änderungs– und Erstelldatum. Befinden sich jedoch etwa eine größere Anzahl von JPEG-Dateien im Verzeichnis, so wechselt der Explorer das Spalten-Set in mehr oder weniger für Bilder nützliche Informationen.

Mit Rechtsklick auf die Spaltenköpfe erscheint ein Popup-Menü, über das Sie andere gebräuchliche Spalten an- oder abwählen können (siehe Bild 1).

Popup des Explorer-Spaltenkopfs

Bild 1: Popup des Explorer-Spaltenkopfs

Benötigen Sie andere Informationen, so erscheint über Weitere… der Dialog in Bild 2, in dem Sie aus einer umfangreichen Liste die gewünschten Einträge markieren, wobei viele nur bestimmten Dateitypen vorbehalten sind, weshalb die dann eingeblendeten Spalten im Zweifel leer bleiben. Das eingestellte Spalten-Set speichert die Windows-Shell pro Ordner persistent, sobald Sie ihn verlassen.

Liste der Dateieigenschaften im Details-Dialog des Explorer für Ordner

Bild 2: Liste der Dateieigenschaften im Details-Dialog des Explorer für Ordner

Klicken Sie auf eine Datei rechts und wählen im Kontextmenü den Eintrag Eigenschaften, so bekommen Sie unter dem Reiter Details allerlei Informationen präsentiert, die sich je nach Dateityp in Inhalt und Umfang unterscheiden (siehe Bild 3).

Informationen zu einer MP3-Datei im Eigenschaftendialog des Explorers

Bild 3: Informationen zu einer MP3-Datei im Eigenschaftendialog des Explorers

Der Name einer Eigenschaft ist dabei jeweils identisch zu jenem, der auch im anderen Dialog oder in den Spaltenköpfen angezeigt wird. Das Gleiche gilt für die Werte. Einige Eigenschaften sind hier sogar editierbar, wenn sich das Wertefeld beim Markieren in eine Textbox verwandelt.

Wir haben es hier überall mit dem sogenannten Property System von Windows zu tun, das in die Shell integriert ist. Und auf dieses können Sie mithilfe einiger Objekte auch in Ihrem VBA-Projekt zugreifen! Der Aufwand dafür hält sich in Grenzen. Es werden im Prinzip nämlich keine jener API-Funktionen benötigt, die man sonst häufig in entsprechenden Routinen zum Auslesen von Dateieigenschaften im Netz findet.

Das Windows Property System

Es wurde in der jetzigen Form mit Windows Vista eingeführt und dient der Abstraktion von Dateieigenschaften im System. über die Ansprache einer einzigen Komponente (propsys.dll) können alle verfügbaren Informationen abgerufen werden. Diese Komponente bemüht ihrerseits andere Komponenten, die die eigentliche Arbeit verrichten, weil nur sie den Aufbau bestimmter Dateitypen kennen. Und außerdem kann das Property System noch durch installierte Programme erweitert werden. Office installiert etwa zusätzliche solcher Property Handler, damit Sie direkt auf Dokumenteigenschaften zugreifen können, ohne eines der Programme starten zu müssen. Dafür gibt es eine festgelegte Schnittstelle. Welche Dateitypen mit welchen Komponenten korrelieren, wird dabei in der Registry festgehalten.

Datenbank für Dateieigenschaften

Die Demo zu diesem Beitrag (FileProps.accdb) enthält alles Nötige für den Umgang mit diesen Dateieigenschaften. Sie können Teile aus ihr problemlos in eigene Projekte übertragen.

Grundvoraussetzung ist zunächst ein Verweis auf die Bibliothek Microsoft Shell Controls And Automation im VBA-Projekt, die sich dann im Objektkatalog als Shell32 zeigt. Die Bibliothek bringt Windows immer mit und kann deshalb ganz ohne Gewissensbisse eingesetzt werden.

Die Prozedur SHGetPropertyString im Modul mdlPropsShell macht sich dann einige Klassenobjekte der Bibliothek zunutze. Mit gerade einmal 20 Zeilen Code erledigt sie das Auslesen beliebiger Datei- und Ordnereigenschaften, die von der Shell unterstützt werden – und das sind eine ganze Menge! Listing 1 zeigt die komplette Routine. Sie übergeben der Funktion im ersten Parameter den vollen Pfad der Datei und im zweiten die gewünschte Eigenschaft. Zurück erhalten Sie dann grundsätzlich den Wert der Eigenschaft als String. Dies wäre ein Beispiel:

Dim oSH As Shell32.Shell
Function SHGetPropertyString(sFile As String, sProp As String) As String
     Dim sFld As String, sFil As String
     Dim oFld As Shell32.Folder3
     Dim oItm As Shell32.ShellFolderItem
     Dim vRet As Variant
     
     If oSH Is Nothing Then Set oSH = New Shell32.Shell
         
     sFld = Left(sFile, InStrRev(sFile, "\") - 1)
     sFil = Mid(sFile, InStrRev(sFile, "\") + 1)
     Set oFld = oSH.NameSpace(CStr(sFld))
     If Len(sFil) = 0 Then
         Set oItm = oFld.Self
     Else
         Set oItm = oFld.Items.Item(CStr(sFil))
     End If
     vRet = oItm.ExtendedProperty(sProp)
     If IsArray(vRet) Then
         SHGetPropertyString = Join(vRet, ";")
     Else
         SHGetPropertyString = vRet
     End If
End Function

Listing 1: Die Funktion gibt eine beliebige Dateieigenschaft zurück

  SHGetPropertyString("d:\mp3s\fullalbum.mp3", "System.Size")
-> "62356466"

Hier wird die Dateigröße der MP3-Datei ermittelt. Setzen Sie als zweiten Parameter System.DateCreated ein, so erhielten Sie das Erstelldatum:

-> "02.11.2017 16:23:48"

Oder mit System.FileOwner den Besitzer der Datei:

-> "MeinComputername\Herbert"

Was es mit diesen Property-Parametern auf sich hat und wie man auf sie kommt, erläutern wir später noch. Hier folgt aber zunächst die Funktionsweise des Codes.

Das zentrale Objekt, von dem sich alles Weitere ableitet, steht in der Objektvariablen oSH vom Typ Shell, die im Modulkopf global deklariert ist. Dieses Objekt kann per New erzeugt werden. Eine Alternative, die ganz ohne Bibliotheksverweis auskommt, wäre

Set oSH = CreateObject("Shell.Application")

Bevor das Objekt benutzt wird, müssen aber aus dem vollen Pfad in sFile erst der Ordner- und der Dateinamenanteil extrahiert werden, was die folgenden zwei Zeilen erledigen. sFld enthält danach den Ordner, sFil den Dateinamen. Um beim vorigen Beispiel zu bleiben:

sFld -> "d:\mp3s"
sFil -> "fullalbum.mp3"

Die NameSpace-Funktion des Shell-Objekts gibt nun ein neues Objekt vom Typ Folder in oFld zurück, wenn man den Pfad übergibt, der hier zusätzlich mit CStr behandelt wird. Manchmal funktioniert die übergabe eines VBA-Strings hier nämlich nicht korrekt und CStr stellt sicher, dass die Funktion einen gültigen COM-String erhält.

Der Clou an der Routine ist, dass Sie ihr nicht nur Dateien, sondern auch Ordner zur Inspektion verabreichen können. In diesem Fall ist die Variable sFil dann leer und die per Len() ermittelte Länge 0. Davon hängt in der Bedingung ab, wie weiter verfahren wird. Denn als nächstes wird die Items-Auflistung des Folder-Objekts bemüht. Das ist im Prinzip das, was der Explorer auf der rechten Seite ausgibt. Ein Item kann eine Datei im Verzeichnis sein, oder ein Unterordner. Da der Explorer auch virtuelle Objekte darstellen kann, wie etwa die Systemsteuerung, könnte ein Item auch ein virtuelles Objekt wiederspiegeln. Selbst dessen Eigenschaften könnten mit der Routine ausgelesen werden, doch das steht hier im Beitrag gerade nicht zur Debatte.

Das Item erhält die Objektvariable oItm vom Typ ShellFolderItem. Für eine Datei übergeben Sie als Index der Auflistung Items den Namen in sFil. Soll der Ordner selbst inspiziert werden, so kann er selbst in ein Item überführt werden, wenn die Methode Self auf den Folder angewandt wird. Und nun sind wir soweit: Vom Item kann die Funktion ExtendedProperty abgerufen werden, der als Parameter der Systemname der Eigenschaft (sProp) übergeben wird. Das Ergebnis steht nun im Variant vRet.

Allerdings gibt diese Methode nicht immer nur einen String zurück, sondern manchmal auch ein ein String-Array. Ein Word-Dokument kann etwa mehrere Autoren aufweisen, die über den Property-Namen System.Author ermittelt würden. Die einzelnen Autoren stünden dann als Elemente eines Arrays im Ergebnis. Die VBA-Funktion IsArray erkennt, ob das Ergebnis ein Array ist. Dann fügt die Join-Funktion die Elemente des Arrays zu einem einzelnen String zusammen.

System Property Names

Was Sie nun noch brauchen, um sämtliche Eigenschaften einer Datei auslesen zu können, sind die Systemnamen der Eigenschaften. Leider gibt es dafür keine generelle Liste. Denn erstens hat jede Windows-Version ihre eigenen abweichenden Systemeigenschaften, und zweitens lässt sich, wie erwähnt, das Property System ja durch neu installierte Programme erweitern, was zu neuen in der Registry eingetragenen Property Names führt.

Leider ist man mit der Shell32-Bibliothek hier am Ende der Fahnenstange angekommen. Sie enthält keine Methoden, um an die Systemnamen zu kommen. Gottlob gibt es aber die in früheren Beträgen bereits erwähnte Type Library oleexp. Vorgestellt wurde sie etwa im Beitrag Explorer Control (Shortlink 1096). Sie stellt, so Sie sie in die Verweise aufnehmen, alle Klassen und Interfaces bereit, die für das Auslesen der Systemnamen benötigt werden.

Die Bibliothek wird übrigens von der Demo beim Start des Intro-Formulars frmIntro automatisch geladen und sollte sich dazu im Verzeichnis der Datenbank befinden:

On Error Resume Next
References.AddFromFile CurrentProject.Path & "\oleexp.tlb"

Die Prozedur StorePropertyKeys im gesonderten Modul mdlPropStore ermittelt dann alle Systemnamen und speichert sie in der Tabelle tblSysProperties. Um es klarzustellen: Dieses Modul brauchen Sie in Ihrer produktiven Datenbank später nicht mehr und eben so wenig den Verweis auf die Bibliothek oleexp!

Es dient hier ausschließlich dazu, um die Tabelle zu füllen, die dann die gefragten Systemnamen enthält. Nur diese brauchen Sie schließlich in Ihre Datenbank zu übernehmen.

Der Aufbau der Tabelle ergibt sich aus Bild 4. Das Feld Systemname erhält den Property-Namen, wie etwa System.Author. In Bezeichnung steht dann die deutsche übersetzung, wie Autoren. Alle anderen Felder sind optional und nur informativ. In Type steht der Datentyp, wie etwa String oder Integer.

In der Entwurfsansicht der Tabelle tblSysProperties ist das Feld Systemname eindeutig indiziert

Bild 4: In der Entwurfsansicht der Tabelle tblSysProperties ist das Feld Systemname eindeutig indiziert

Da die Methode ExtendedProperty immer Strings zurückgibt, kann man nicht erkennen, um welche Art von Wert es sich handelt. Type gibt einen Rückschluss darauf. Flags wiederum ist ein Feld, das Hexadezimal-Strings ausgibt, welche weitere Informationen über die Art der Eigenschaft hervorbringen.

Es führt hier zu weit, dies zu erläutern und ich verweise auf den auskommentierten Block Property Type Flags im Kopf des Moduls mdlPropStore.

HasCategory schließlich gibt Auskunft darüber, ob es sich bei der Eigenschaft um ein Element einer bestimmten Kategorie handelt. Eigenschaften können nämlich kategorisiert werden. Die Hauptkategorie ist System. Das sind alle in Windows verbauten Eigenschaften, wie beispielsweise System.FileOwner. Hier kann es aber Unterkategorien geben. Bei Bildern etwa kommt die Kategorie System.Image ins Spiel, die selbst keine Eigenschaft darstellt. System.Image.HorizontalSize aber gibt die horizontale Ausdehnung der Bilddatei zurück. Alle Systemnamen, die mehr, als einen Punkt enthalten, sind Teil einer solchen Unterkategorie.

Eigenschaften hingegen, die von installierten Programmen ermittelt werden, haben nicht die Hauptkategorie System, sondern eigene. Hier ist auf dem Rechner etwa die Corel Graphics Suite installiert, die zusätzliche Property Handler implementiert.

Die Hauptkategorie ist hier Corel und eine Eigenschaft wäre Corel.File.CompressionRatio, die zurückgibt, wie stark die Bilddatei komprimiert ist. Das allerdings funktioniert nur mit den speziellen Corel-Dateitypen, wie .cdr. Wie sich schließlich der Inhalt der Tabelle in der Datenblattansicht darstellt, zeigt Bild 5.

Ausschnitt der Datenblattansicht der Tabelle tblSysProperties mit allen für das System ermittelten Shell-Properties

Bild 5: Ausschnitt der Datenblattansicht der Tabelle tblSysProperties mit allen für das System ermittelten Shell-Properties

Nur der Vollständigkeit halber ist in Listing 2 die Routine abgebildet, welche die Systemnamen enumeriert und in die Tabelle speichert. Es liegt deutlich außerhalb des Horizonts dieses Beitrags, ihre Funktionsweise zu erläutern, denn hier kommen recht exotische Interfaces und Methoden zum Einsatz. Es sollte reichen, wenn Sie wissen, was sie tut.

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar