(Aufnahme) Datum aus einer Datei ermitteln

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von DTF.

    (Aufnahme) Datum aus einer Datei ermitteln

    Hallo, mein Vater hat 1000de Bilder / Videos.
    Bei einigen ist das Erstellungsdatum (der Bilder / Videos) - nicht des Datum, wann das Bild auf die Festplatte kopiert wurde - im Dateinamen enthalten. Das ist dann kein Problem.
    Bei Bildern kann ich das Datum (falls vorhanden) mittels "Image.PropertyItems" aus der Datei auslesen. Leider weiß ich nicht wie ich das bei einem Video, beispielsweise *.mp4 machen kann.
    Über die Dateieigenschaften von Windows kann ich mir das Datum anzeigen lassen, siehe Anhang

    Jemand eine Idee?

    *Topic verschoben*
    Bilder
    • Unbenannt.png

      15,28 kB, 367×375, 52 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Windows nutzt für den Eigenschaften-Dialog das COM-Interface IPropertyStore -> learn.microsoft.com/de-de/wind…nn-propsys-ipropertystore Das COM-Interface erstellst per API SHGetPropertyStoreFromParsingName -> learn.microsoft.com/en-us/wind…pertystorefromparsingname von der Datei wo Du die Infos auslesen/schreiben möchtest.
    Mfg -Franky-
    Danke schon mal dafür, aktuell habe ich mir den "MediaInfo.DotNetWrapper 1.0.7" installiert und wie folgt ins Programm eingebunden:

    VB.NET-Quellcode

    1. Imports MediaInfo


    VB.NET-Quellcode

    1. Dim test As New MediaInfo.DotNetWrapper.MediaInfo
    2. test.Open(path)


    Hier endet bisher mein Verständnis...

    --Edit--

    Ich glaube so komme ich an die Infos:

    VB.NET-Quellcode

    1. Dim Mi As New MediaInfo.DotNetWrapper.MediaInfo
    2. Mi.Open(filename)
    3. Dim Info As New TextBox
    4. Info.Text = Mi.Inform()

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Humax“ ()

    Hmm, dafür extra ein Wrapper für eine DLL, eines Drittherstellers, installieren der nur Audio und Video kann obwohl Dir Windows bereits alles zur Verfügung stellt um entsprechende Infos, und das für alle Shell-Objekte, auszulesen? *Kopfkratz*
    Mfg -Franky-
    Ja wenn man weis wie, kein Problem. Hab mich jetzt auch dran versucht, klappt bisher. @-Franky- ich find da keine gescheite Liste für die Guids von PROPERTYKEY.fmtid, ich hab jetzt zumindest das ErstellDatum finden können hab aber 4 verschiedene Guids mit diesem Datum, also ist das Datum noch anderswo mehrfach in den Metas.

    Auszug aus der Debugausgabe: (Links GUID, rechts Datum)
    b725f130-47ef-101a-a5f1-02608c9eebac___________5.7.2021
    f29f85e0-4ff9-1068-ab91-08002b27b3d9___________5.7.2021
    f7db74b4-4287-4103-afba-f1b13dcd75cf___________5.7.2021
    14b81da1-0135-4d31-96d9-6cbfc9671a99___________5.7.2021
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Hier gab es da schonmal was zu. Allerdings n bissle kurz gegriffen fürn Tutorial find ich. Oder hier auch was

    Also am Ende kommt man bei sowas rum:

    VB.NET-Quellcode

    1. Imports Shell32
    2. Private Function GetDetail(fi As FileInfo, idx As Integer) As String
    3. Dim shell As New Shell()
    4. Dim folder As Folder = shell.NameSpace(fi.DirectoryName)
    5. Return folder.GetDetailsOf(DirectCast(folder.Items().Item(fi.Name), FolderItem2), idx)
    6. End Function
    Da muss man nur einmal den richtigen Index für Mediumsdatum rausfinden. Da kenn ich keine Liste zu, wirds aber sicher auch geben, und sonst muss man wohl mal da durchsuchen.

    Aber das ist unmanaged Code soweit ich das verstehe. Bezüglich aufräumen sieht man andere anschließend nur die Verweise auf Nothing setzen.
    Ob man da noch irgendwas extra machen sollte z.B. Marshal.FinalReleaseComObject? Ich weiß nicht ob sich da was sperren kann wie bei Excel^^

    Haudruferzappeltnoch schrieb:

    Oder hier auch was


    Hier jetzt auch mit der Variante die -Franky- vorgeschlagen hat. So schauts im groben aus:(Experimentiermappe im Anhang, Kommentar zur HRESULT Struktur, die ist nicht komplett, muss hier in diesem Fall nicht, hatte was rausgenommen, weil ich das auf nötigste reduziert hab, damit das übersichtlich bleibt. Die anderen Facilities sind hier ja unwichtig.(PS. Hab sogar die falsche HRESULT Datei ins Projekt gepackt, war aus einen alten testprojekt, dachte war aus dem aktuellen. Und im IPropertyStore sollten alle Funktionen das [PreserveSig] Attribute haben. Habs nur bei GetCount gemacht :S

    Sollte ich nicht falsch liegen, ist System.ItemDate
    learn.microsoft.com/de-de/wind…ies/props-system-itemdate
    das Erstelldatum. Bei Photos, kann das schon wieder was anderes sein, System.Photo.DateTaken.

    Das beste was man machen kann, die Guids die kommen, einfach mal in eine Suchmaschine werfen.

    @-Franky-
    Ich hab auch mehrmals die gleiche Guid mit verschiedene Datumsen, darf ich das wie eine Auflistung von Datums wo ein Ereignis statt gefunden hat verstehen?(z.B. verschoben?)

    C#-Quellcode

    1. IPropertyStore propStore;
    2. Guid guidProeprtyStore = new Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99");
    3. HRESULT hr = NativeMethods.SHGetPropertyStoreFromParsingName("E:\\Movie\\8 mm - Acht Millimeter\\8mm Acht Millimeter.mp4", 0, 0, ref guidProeprtyStore, out propStore);
    4. if(hr.Code == HRESULT.S_OK)
    5. {
    6. int count = 0;
    7. hr = propStore.GetCount(out count);
    8. if (hr.Code == HRESULT.S_OK)
    9. {
    10. for(int i = 0; i < count; i++)
    11. {
    12. PROPERTYKEY propKey;
    13. hr = propStore.GetAt(i, out propKey);
    14. if (hr.Code == HRESULT.S_OK)
    15. {
    16. Guid guidItemDate = new Guid("f7db74b4-4287-4103-afba-f1b13dcd75cf");
    17. if(guidItemDate.Equals(propKey.fmtid))
    18. {
    19. PROPVARIANT propVar;
    20. hr = propStore.GetValue(propKey, out propVar);
    21. if (hr.Code == HRESULT.S_OK)
    22. {
    23. NativeMethods.SYSTEMTIME systime;
    24. if (NativeMethods.FileTimeToSystemTime(ref propVar.filetime, out systime))
    25. {
    26. Debug.WriteLine(propKey.fmtid.ToString() + "___________" + systime.wDay + "." + systime.wMonth + "." + systime.wYear);
    27. }
    28. }
    29. }
    30. }
    31. }
    32. }
    33. }

    Dateien
    • WinFormsApp2.zip

      (102,36 kB, 50 mal heruntergeladen, zuletzt: )
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    Am besten ist man konvertiert den PROPERTYKEY den IPropertyStore.GetAt liefert per API PSGetNameFromPropertyKey in seinen CanonicalName bzw kann man diesem per API PSGetPropertyKeyFromName wieder in eine PROPERTYKEY konvertieren. Das ist der Vorteil gegenüber der GetDetailsOf-Methode. Dann gibt es noch die API PSGetPropertyDescription mit der man weitere COM Interfaces von einem PROPERTYKEY erstellen kann. z.B. Das COM Interface IPropertyDescription.

    Edit: Nicht nur die FMTID ist wichtig, auch die PID. Die FMTID beschreibt sozusagen ein PropertySet für Audio, Video, Media usw. Die PID dann welcher Property aus dem PropertySet gelesen werden soll.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Das hört sich gut an, werde ich mir morgen früh ansehen. Hätte mich schon eher damit(COM-Interface in NET) beschäftigen sollen. Das sind sehr nützliche Skills.

    PS
    @-Franky-
    Ja die pid hatte ich schon garnicht mehr im Sinn, schien mir beim tippen weniger wichtig, weil viel konnt ich bei MS nicht erfahren.
    A property identifier (PID). This parameter is not used as in SHCOLUMNID. It is recommended that you set this value to PID_FIRST_USABLE. Any value greater than or equal to 2 is acceptable.


    Ich werde morgen früh eine flood attacke auf die Debugausgabe starten. Mal schauen, was so noch auslesbar ist auf diese Weise.

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    @DTF Für die Suche nach Const, Enums, CLSIDs, IIDs usw kann ich nur magnumdb.com/ empfehlen. Zur Vollständigkeit: Man kann für Audio und Video auch die MediaFoundation nutzen um entsprechende Tags auszulesen oder zu schreiben. Die WinRT bietet ebenfalls über den Namespace Windows.Storage.FileProperties die Möglichkeit an Tags auszulesen. <- Nutz im Hintergrund auch IPropertyStore.

    @Haudruferzappeltnoch Den Verweis auf die Shell und Automation würde ich heute nur bedingt empfehlen. MS hat diese Referenz seit Jahren nicht mehr aktualisiert. Da fehlen komplett die neuen Shell COM Interfaces und die die vorhandenen sind, sind nicht komplett bzw sehr eingeschränkt nutzbar.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Also die Datenbank ist Top, mal eben nach den schon oben gezeigten Guids gesucht und Ergebnisse bekommen.

    Quellcode

    1. PKEY_DateAccessed, PropertyKey, {b725f130-47ef-101a-a5f1-02608c9eebac} 16
    2. PKEY_DateCreated, PropertyKey, {b725f130-47ef-101a-a5f1-02608c9eebac} 15
    3. PKEY_DateModified, PropertyKey, {b725f130-47ef-101a-a5f1-02608c9eebac} 14


    Das bringt Licht in die Sache.

    PS:
    hab eben mal geschaut, die Zahlen hinter den Guids sind dann die property id.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    Haudruferzappeltnoch schrieb:

    In DTFs Sample sind >10000 Zeilen Code


    Aber auch nur, weil die SystemErrorCodes alle(wirklich alle die bei MS gelistet sind) drin sind :D , pro Wert kommen dann noch 3 Zeilen XmlComment hinzu. Schau dir einfach das Interface an, die Structs, das ist das relevante. Am wichtigsten ist das Interface, schau dir dessen Funtionen an. Die Instanz bekommen wir mit der SHGetPropertyStoreFromParsingName funktion.

    Gut das ich alles mit den Facilities rausgenommen hab. Die SystemErrorCodes sind auch nur drin, weil ich in HRESULT diese Funktion drin gelassen hab, HRESULT FromWin32ErrorCode(SystemErrorCodes code). Daher dort auch die fixe 7, weil 7 die Win32 Facility ist.

    Für die, die mal schauen wollen was ein HRESULT genau ist:
    en.wikipedia.org/wiki/HRESULT
    Dazu eine tolle Seite, mit den ganzen Facilities:
    hresult.info/Facilities
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    @Haudruferzappeltnoch Brauchen nicht unbedingt. Kommt auf den Anspruch an, den man an sich selbst stellt. Nehmen wir mal GetDetailsOf bzw die Referenz auf die Shell und Automation. Wie kommst Du da an die Anzahl der verfügbaren Properties zu einem ShellItem/ShellFolder? Wie ist der Name (PKey_xxx/CanonicalName) des Property? Kannst Du gezielt ein Property auslesen wenn Du nur den PKey_xxx/CanonicalName kennst? Gibt es in der Referenz IShellItem2::GetPropertyStore oder die Struct PROPERTYKEY oder PROPVARIANT? usw usw. Klar kann man einen Index bei GetDetailsOf angeben, aber was da genau zurückgeben wird weiß man nicht wirklich (vllt noch die ersten 50) es sei den es gibt irgendwo eine Enum mit Namen zum Index bzw warum sollte ich einen Index abfragen den es in einem Audio gibt, aber nicht in einem PDF zb. Welcher Index wäre den die Anzahl der Wörter in einem Worddokument usw? Wenn Du mit diesen Einschränkungen leben kannst, why not. Ich kann es nicht. :D

    Und nein, Studieren musst Du auch nicht dazu. Evtl ein wenig damit beschäftigen was mit COM so geht.

    Edit: Falls Du doch lieber mit Referenzen arbeitest und Dir viel getippel sparen möchtest, dann schau Dir das Projekt oleexp.tlb auf vbforums an. Diese TLB kannst Dir ja als Referenz in Deinem Projekt einbinden. Die TLB wird von Fafalone immer wieder mal aktualisiert so das fasst alle COM Interfaces komplett vorhanden sind. -> vbforums.com/showthread.php?78…e-Type-Library-oleexp-tlb
    Mfg -Franky-

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „-Franky-“ ()

    @Haudruferzappeltnoch
    Falls dich die HRESULT Struktur verwirrt, werf die raus und verwende einfach int/uint. dann schauen ob die funktionen 0(S_OK) zurückgeben. Gestern im müden yustand, habe ich nur den hr.Code auf 0 geprüft, wenn HRESULT komplett 0 ist, ist das S_OK.

    Um zu erfahren in welcher Reihenfolge die Funktionen in den Interfaces sein müssen, schau bei MS nach dem Interface, dort kannst du dann erfahren in welchen Header die zu finden sind. Dann suchst du nach dem Header, oder eine .IDL mit dem selben Namen. Hier ein Auszug aus einer IDL

    Quellcode

    1. [
    2. uuid(886d8eeb-8cf2-4446-8d02-cdba1dbdcf99),
    3. object,
    4. pointer_default(unique)
    5. ]
    6. interface IPropertyStore : IUnknown
    7. {
    8. HRESULT GetCount(
    9. [out] DWORD *cProps
    10. );
    11. HRESULT GetAt(
    12. [in] DWORD iProp,
    13. [out] PROPERTYKEY *pkey
    14. );
    15. HRESULT GetValue(
    16. [in] REFPROPERTYKEY key,
    17. [out] PROPVARIANT *pv
    18. );
    19. HRESULT SetValue(
    20. [in] REFPROPERTYKEY key,
    21. [in] REFPROPVARIANT propvar
    22. );
    23. HRESULT Commit(void);
    24. }


    Wenn du nun in mein Interface schaust, genau die gleiche Reihenfolge, die Guid haben auch auch direkt dabei. Nun schau mal genau die Typen an, PROPERTYKEY, REFPROPERTYKEY. an dem vorrangestellen REF sieht man das die Referenz gebraucht wird, dann ref bzw. ByRef verwenden. Das gleiche siehst du dann auch mit PROPVARIANT und REFPROPVARIANT.

    Aber @-Franky- hat absolut recht, studiert hab ich nie, alles was ich in dem Bereich kann, hab ich auf eigene Faust gelernt. wenn man weis wie man die Interfaces macht, weis auf welche Art man eine Instanz bekommt ist das einfach. Alles weitere ist bei MS gut dokumentiert. Aber ich finde, meine C++ Kenntnisse sind hier ein richtiger Vorteil.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()