evinben
Goto Top

Dateieigenschaften aus der Registerkarte (Details) auslesen und als Text kopieren

Hallo,

unter Eigenschaften einer .exe-Datei gibt es auf der Registerkarte „Details“ Informationen, welche sich leider nicht kopieren lassen. Wäre es irgendwie möglich diese Informationen abzufragen?
Auf dem nachfolgenden Bild sieht man, was ich meine
213c9992d5349297262d406a009355d6

Etwas ähnliches macht das vbs-Skript hier:
'Aufruf z. B. in der CMD wie folgt  
'cscript //nologo Datei-Eigenschaften_auslesen.vbs c:\Pfad_zum_Ordner >> Dateiliste.txt  

Set objShell = CreateObject("Shell.Application")  
Set objFolder = objShell.Namespace(Wscript.arguments(0))

For Each strFileName in objFolder.Items
   
    strName = objFolder.GetDetailsOf(strFileName, 0)
	If InstrRev(strName, ".") > 1 Then strName = Left(strName, InstrRev(strName, ".") - 1)  
	Wscript.echo strName & " " & objFolder.GetDetailsOf(strFileName, 14)  
    
Next
Hier kann man über DateCreated Property nachlesen: http://msdn.microsoft.com/en-us/library/ke6a7czx(VS.85).aspx
Und unten werden alle möglichen Eigenschaften als Referenz dazu aufgelistet:

Attributes Property
DateLastAccessed Property
DateLastModified Property
Drive Property
Files Property (FileSystemObject)
IsRootFolder Property
Name Property (FileSystemObject)
ParentFolder Property
Path Property (FileSystemObject)
ShortName Property
ShortPath Property
Size Property
SubFolders Property
Type Property

In meinem Falle müssen jedoch die Details-Informationen abgefragt werden (vor allem die Attribute Dateiversion und Produktversion).
Und im Gegensatz zu dem obigen Skript einen ganzen Ordner zu durchsuchen, plane ich nur die ausgewählten Dateien als Argument zu verarbeiten (indem ich sie einfach auf eine Batch-Datei oder vbs-Skript ziehe und loslasse, bzw. über sendto an das Skript sende) und dann z. B. in sich öffnendem CMD-Fenster oder einer txt-Datei die notwendigen Informationen herauskopiere.

Danke für paar Anregungen zur Lösung dieses Problems.

Gruß
evinben

Content-Key: 241735

Url: https://administrator.de/contentid/241735

Printed on: May 9, 2024 at 01:05 o'clock

Member: colinardo
colinardo Jun 24, 2014, updated at Jun 25, 2014 at 06:24:07 (UTC)
Goto Top
Moin envinben,
dafür habe ich mal eine Powershell-Funktion geschrieben:
Erweiterte Dateieigenschaften mit Powershell-Funktion abfragen

Passend dazu dann ein Aufruf mit der obigen Funktion und Anzeige nur deiner bevorzugten Eigenschaften:
dir "c:\testdatei.exe" | Add-ExtendedFileProperties | select Name,Dateiversion,Produktversion

Zusammengefasst in einer .ps1 Datei, könnte das dann so aussehen: Dem Script übergibt man als Parameter einen Dateipfad, und als Ergebnis werden alle Dateieigenschaften in die Zwischenablage kopiert. Der Aufruf erfolgt dann z.B. so "C:\copy-fileproperties.ps1" "C:\deinedatei.exe"
back-to-topcopy-fileproperties.ps1
param(
  [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][string]$file
)

function Add-ExtendedFileProperties{
 <#
     .SYNOPSIS
        Fügt erweiterte Eigenschaften von Dateien an das Objekt in der Pipline hinzu
     .DESCRIPTION
        Extrahiert erweiterte Eigenschaften von Dateien wie z.B. Exif-Daten, Musik- bzw. Filmdetails
     .EXAMPLE 
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties -PropertyExtended "Bildhöhe","Bildbreite","Bitrate" | ft Name,Bildhöhe,Bildbreite,Bitrate  
            Fügt alle nur die Eigenschaften "Bildhöhe","Bildbreite","Bitrate" als zusätzliche Spalten dem Objekt in der Pipline hinzu  
     .EXAMPLE
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties | fl *  
            Fügt alle verfügbaren erweiterten Eigenschaften dem Objekt in der Pipline hinzu
     .PARAMETER PropertyExtended
        Mit diesem Parameter geben sie eine Komma-Separierte Liste von Eigenschaften an welche sie erhalten möchten.
            -PropertyExtended "Bildhöhe","Bildbreite","Bitrate"  
#>
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        $fileItem,
        [String[]] $PropertyExtended = "ALL"  
    )
    begin
    {
        $shellObject = New-Object -Com Shell.Application
        $itemProperties = $null
    }

    process
    {
        if($fileItem.PsIsContainer)
        {
            $fileItem
            return
        }
        $directoryName = $fileItem.DirectoryName
        $filename = $fileItem.Name

        $folderObject = $shellObject.NameSpace($directoryName)
        $item = $folderObject.ParseName($filename)

        if(-not $itemProperties)
        {
            $itemProperties = @{}
            $counter = 0
            $columnName = ""  
            if ($PropertyExtended -eq "ALL"){  
                 #get all properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    if($columnName) { $itemProperties[$counter] = $columnName }
                    $counter++
                }while($columnName)
            }else{
                #get user defined properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    foreach($name in $PropertyExtended){
                        if ($columnName.toLower() -eq $name.toLower()){
                            $itemProperties[$counter] = $columnName
                        }
                    }
                    $counter++
                }while($columnName)
            }
        }

        foreach($itemProperty in $itemProperties.Keys)
        {
            $fileItem | Add-Member NoteProperty $itemProperties[$itemProperty] `
                $folderObject.GetDetailsOf($item, $itemProperty) -ErrorAction `
                SilentlyContinue
        }
        $fileItem
    }
}
if ((Test-Path $file)){
    $infos = dir $file | Add-ExtendedFileProperties | fl * | out-string
    [Windows.Clipboard]::SetText($infos)
    Write-host "Daten wurden in die Zwischenablage kopiert!" -ForegroundColor Green  
}else{
    write-host "Die Datei konnte nicht gefunden werden" -ForegroundColor Red  
}
Grüße Uwe
Mitglied: 116301
116301 Jun 24, 2014 updated at 17:46:10 (UTC)
Goto Top
Hallo evinben!

Und in VBS in etwa so:
Const Liste = "D:\Temp\Namespace-Liste.txt"    'Pfad für Liste mit DetailOf-Namen und zugehöriger Nummer  

Const D_Name = 0
Const D_Dateiversion = 156
Const D_Produktversion = 271


'Dieser Code erzeugt eine Text-Liste mit allen DetailOf-Namen  
Sub ListDetailOfNames()
    Dim objFolder, strName, strText
    
    Set objFolder = CreateObject("Shell.Application").Namespace("C:\Windows")  
    
    For Each strName In objFolder.Items
        For i = 0 To 300
            strText = strText & Right("00" & i, 3) & " - " & objFolder.GetDetailsOf(Null, i) & vbNewLine  
        Next
        Exit For
    Next

    CreateObject("Scripting.FileSystemObject").CreateTextFile(Liste).Write strText  
End Sub


Sub ReadDetailOfFiles()
    Dim objShell, objFolder, strFileName, strName, strDateiversion, strProduktversion
    
    Set objShell = CreateObject("Shell.Application")  
    
    Set objFolder = objShell.Namespace(Wscript.arguments(0))
    
    For Each strFileName In objFolder.Items
        With objFolder
            strName = Split(.GetDetailsOf(strFileName, D_Name), ".")(0)  
            strDateiversion = .GetDetailsOf(strFileName, D_Dateiversion)
            strProduktversion = .GetDetailsOf(strFileName, D_Produktversion)
        End With
    Next
End Sub

Grüße Dieter
Member: evinben
evinben Jun 25, 2014 updated at 10:42:28 (UTC)
Goto Top
Hallo Uwe,

umfangreich gemacht. Danke schön für die Anleitung! Auf diese war ich bei der Recherche vor etwa drei Monaten leider nicht gestoßen.

Der Aufruf erfolgt dann z.B. so C:\copy-fileproperties.ps1 "C:\deinedatei.exe"
Wenn ich es so z. B. in der Eingabeaufforderung aufrufe, dann wird nur das Skript im Notepad geöffnet, aber die Eigenschaften werden nicht in die Zwischenablage kopiert.
Momentan muss ich das Skript über das Kontextmenü mit der Option „Mit PowerShell ausführen“ ausführen und in der Shell direkt den Pfad zur Datei eingebe und es funktioniert so. Ein Pfad ohne Anführungszeichen wird jedoch nicht akzeptiert, so wie oben angegeben wurde.
Wie könnte ich aus einer Batch-Datei so aufrufen, damit das gleiche passiert (bzw. die Ausgabe nur auf die Eigenschaften „Dateiversion“ und „Produktversion“ begrenzen)?
Und wie könnte der Text direkt in der Konsole angezeigt werden (anstatt des Kopierens in die Zwischenablage)?

Passend dazu dann ein Aufruf mit der obigen Funktion und Anzeige nur deiner bevorzugten Eigenschaften:
dir "c:\testdatei.exe" | Add-ExtendedFileProperties | select Name,Dateiversion,Produktversion

Dieser Aufruf ist für mich momentan leider ein Rätsel. Wie soll ich das Skript genau aufrufen?

Hallo Dieter,

danke schön.
Wenn ich das vbs-Skript wie folgt so ausführe
GetFileProperties.vbs "file.exe"  
und dabei eine Datei "Namespace-Liste.txt" im Verzeichnis "D:\Temp\" erstelle, werden keine Informationen reingeschrieben.
Bzw. korrigiere mich bitte, wie ich genau vorgehen soll.

Was machen die Zahlen hier genau, wäre dies eine Art Filter?
Const D_Dateiversion = 156
Const D_Produktversion = 271

Gruß
evinben
Mitglied: 116301
116301 Jun 25, 2014 updated at 06:24:06 (UTC)
Goto Top
Hallo evinben!

Das ist kein fertiges Script zur Ausführung. Die erste Sub zeigt nur, wie man per VBS die Eigenschaftsnamen ermitteln und in eine Text-Datei schreiben kann und die zweite Sub nur, wie man die Details ausliest (aktuell ohne Textexport).

und dabei eine Datei "Namespace-Liste.txt" im Verzeichnis "D:\Temp\" erstelle, werde keine Informationen reingeschrieben.
Die Datei wird vom Script unter der angegebenen Pfadangabe (z.B. "E:\Test\Dateiname) erzeugt...

Const D_Dateiversion = 156
Sind festgelegte Konstanten, die der Zahl zwecks besserer Lesbarkeit einen Namen geben:
objFolder.GetDetailsOf(strFileName, 156)
'oder  
objFolder.GetDetailsOf(strFileName, D_Dateiversion)
Haben beide den gleichen Effekt...

Mit diesem VB-Script kannst Du eine Liste mit Detailnamen erzeugen:
'Erzeugt eine Liste (Pfad anpassen) mit DetailOf-Namen und zugehöriger Nummer  
Const Liste = "E:\Test\Namespace-Liste.txt"      

Dim objFolder, strName, strText, i
    
Set objFolder = CreateObject("Shell.Application").Namespace("C:\")  
    
For Each strName In objFolder.Items
    For i = 0 To 300
        strText = strText & Right("00" & i, 3) & " - " & objFolder.GetDetailsOf(Null, i) & vbNewLine  
    Next
    Exit For
Next

CreateObject("Scripting.FileSystemObject").CreateTextFile(Liste).Write strText  
Aus dieser Liste kannst Du die Detailnamen aussuchen, die für Dich wichtig sind...

Zum Auslesen wäre es interessant zu wissen, ob Du nur einzelne Dateien oder z.B. alle *.exe-Dateien in einem Ordner auslesen willst. Außerdem, ob Du die Ausgabe Zeilenweise oder im Csv-Format haben möchtest?

Grüße Dieter
Member: colinardo
colinardo Jun 25, 2014 updated at 12:14:03 (UTC)
Goto Top
Hallo Enviben,
die Anführungszeichen hatte ich vergessen, sorry dafür.
Der Aufruf in einer Batch ist auch kein Problem, dazu schreibst du dir folgende Batch:
@echo off
powershell.exe ".'E:\Pfad zum Script\show_fileattributes.ps1' '%~1'"  
pause
Dann kannst du der Batchdatei über den ersten Parameter den Pfad des Files mit übergeben, oder dein File via Sendas oder Drag n' Drop drauf werfen. Mit diesem abgeänderten Script zeigt es dann nur deine gewünschten Eigenschaften direkt in der Konsole an:
param(
    [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][string]$file
)

function Add-ExtendedFileProperties{
 <#
     .SYNOPSIS
        Fügt erweiterte Eigenschaften von Dateien an das Objekt in der Pipline hinzu
     .DESCRIPTION
        Extrahiert erweiterte Eigenschaften von Dateien wie z.B. Exif-Daten, Musik- bzw. Filmdetails
     .EXAMPLE 
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties -PropertyExtended "Bildhöhe","Bildbreite","Bitrate" | ft Name,Bildhöhe,Bildbreite,Bitrate  
            Fügt alle nur die Eigenschaften "Bildhöhe","Bildbreite","Bitrate" als zusätzliche Spalten dem Objekt in der Pipline hinzu  
     .EXAMPLE
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties | fl *  
            Fügt alle verfügbaren erweiterten Eigenschaften dem Objekt in der Pipline hinzu
     .PARAMETER PropertyExtended
        Mit diesem Parameter geben sie eine Komma-Separierte Liste von Eigenschaften an welche sie erhalten möchten.
            -PropertyExtended "Bildhöhe","Bildbreite","Bitrate"  
#>
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        $fileItem,
        [String[]] $PropertyExtended = "ALL"  
    )
    begin
    {
        $shellObject = New-Object -Com Shell.Application
        $itemProperties = $null
    }

    process
    {
        if($fileItem.PsIsContainer)
        {
            $fileItem
            return
        }
        $directoryName = $fileItem.DirectoryName
        $filename = $fileItem.Name

        $folderObject = $shellObject.NameSpace($directoryName)
        $item = $folderObject.ParseName($filename)

        if(-not $itemProperties)
        {
            $itemProperties = @{}
            $counter = 0
            $columnName = ""  
            if ($PropertyExtended -eq "ALL"){  
                 #get all properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    if($columnName) { $itemProperties[$counter] = $columnName }
                    $counter++
                }while($columnName)
            }else{
                #get user defined properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    foreach($name in $PropertyExtended){
                        if ($columnName.toLower() -eq $name.toLower()){
                            $itemProperties[$counter] = $columnName
                        }
                    }
                    $counter++
                }while($columnName)
            }
        }

        foreach($itemProperty in $itemProperties.Keys)
        {
            $fileItem | Add-Member NoteProperty $itemProperties[$itemProperty] `
                $folderObject.GetDetailsOf($item, $itemProperty) -ErrorAction `
                SilentlyContinue
        }
        $fileItem
    }
}
if ((Test-Path $file)){
    dir $file | Add-ExtendedFileProperties -PropertyExtended Dateiversion,Produktversion | fl Dateiversion,Produktversion
}else{
    write-host "Die Datei konnte nicht gefunden werden" -ForegroundColor Red  
}
Grüße Uwe
Member: evinben
evinben Jun 25, 2014 at 11:06:41 (UTC)
Goto Top
Hallo Dieter,

Zum Auslesen wäre es interessant zu wissen, ob Du nur einzelne Dateien oder z.B. alle *.exe-Dateien in einem Ordner auslesen willst.
ne, ne, so wie ich ganz am Anfang an geschrieben habe:
Und im Gegensatz zu dem obigen Skript einen ganzen Ordner zu durchsuchen, plane ich nur die ausgewählten Dateien als Argument zu verarbeiten (indem ich sie einfach auf eine Batch-Datei oder vbs-Skript ziehe und loslasse, bzw. über sendto an das Skript sende)...
Eine zeilenweise Ausgabe ist völlig ausreichend.
Es geht hier lediglich darum bei einem Vergleich anstatt die langen Nummer manuell abzutippen (und dabei eventuelle Fehler zu machen) diese schnell zu kopieren.

Gruß
evinben
Member: evinben
evinben Jun 25, 2014 updated at 11:53:13 (UTC)
Goto Top
Hallo Uwe,

die Anführungszeichen hatte ich vergessen, sorry dafür.
heißt es du hast den Code zuletzt so angepasst, dass Eingabe des Pfades auch in Anführungszeichen möglich wäre? Weil ich die folgende Ausgabe erhalte:
PS D:\Datei-Eigenschaften auslesen> D:\Datei-Eigenschaften auslesen\GetFileproperties.ps1
Die Datei konnte nicht gefunden werden
und ohne die Anführungszeichen dann wie erwartet:
PS D:\Datei-Eigenschaften auslesen> D:\Datei-Eigenschaften auslesen\GetFileproperties.ps1


Dateiversion   : 1.0.1.131
Produktversion : 1, 0, 1, 131

Und mit dem folgenden Syntax in einer Batch
powershell.exe "C:\VollständigerPfadzumScript.ps1" "%1"
bekomme ich die folgende Ausgabe beim Ausführung per Drag&Drop:
Die Benennung "D:\Datei-Eigenschaften" wurde nicht als Name eines Cmdlet, einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt. Überprüfen Sie die Schreibweise des Namens, oder ob der Pfad korrekt ist (sofern enthalten), und wiederholen Sie den Vorgang.  
Bei Zeile:1 Zeichen:23
+ D:\Datei-Eigenschaften <<<<  auslesen\GetFileproperties.ps1 D:\Datei-Eigenschaften auslesen\TextFile.exe
    + CategoryInfo          : ObjectNotFound: (D:\Datei-Eigenschaften:String) , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Das von dir angegebene Argument am Ende des Aufrufs soll zwar 1% (bzw. "%~1") lauten, aber das Hauptproblem liegt irgendwo anders...
Also obwohl der Pfad in Anführungszeichen gesetzt worden ist, werden die Leerzeichen von PowerShell weiterhin als Trennzeichen behandelt.

Gruß
evinben
Member: colinardo
Solution colinardo Jun 25, 2014 updated at 14:34:25 (UTC)
Goto Top
Ach, meine Güte wo ist mein Kopf heute - sorry - es muss natürlich so aussehen:
@echo off
powershell.exe ".'D:\Datei-Eigenschaften auslesen\GetFileproperties.ps1' '%~1'"  
pause
(bitte den Punkt vor dem Pfad nicht entfernen, der muss da stehen)
Grüße Uwe

(habe es oben auch korrigiert)
Member: evinben
evinben Jun 25, 2014 at 15:03:03 (UTC)
Goto Top
sauber face-wink, es funktioniert nun!
Mir reicht es momentan so wie es ist aus. Es wäre einfacher nur reine ps1-Datei zu haben und an diese die Parameter über die Batch-Datei zu übergeben. Solltest du auf Anhieb wissen wie ein Argument im PowerShell-Skript empfangen werden kann, dann werde ich es bei Gelegenheit versuchen. Aber jetzt Schluss damit.

Gruß
evinben
Member: colinardo
colinardo Jun 25, 2014 updated at 15:23:40 (UTC)
Goto Top
du kannst dir einfach eine neue Verknüpfung anlegen und dies dort reinschreiben:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -noexit -File "D:\Datei-Eigenschaften auslesen\GetFileproperties.ps1"
dann kannst du auf diese Verknüpfung dein File werfen, und benötigst keine Zwischenbatch mehr.
Member: evinben
evinben Jun 25, 2014 at 16:12:54 (UTC)
Goto Top
dann besteht aber das Problem mit der Pfadbeziehung. In einer Batch habe ich mit %~dp0
PushD %~dp0
powershell.exe ".'%~dp0GetFileProperties.ps1'" '%~1'"  
immer die Verbindung zu dem externem Skript, auch wenn sich der Pfade ändert.
Bzw. es könnte eventuell auch möglich sein die absolute oder auch die relative Pfadbeziehung in einer Verknüpfung zu erzwingen - aber dies wäre mir neues.
Dennoch gut zu wissen mit der Verknüpfung und daher habe ich mir es gleich als zusätzliche Möglichkeit aufgenommen.
Ich hab mir eine Verknüpfung in SendTo zu der Batch-Datei angelegt und so läuft es mit meiner Erfahrung auf Dauer ohne Überraschungen robust, da egal wo sich die beiden Dateien dann letztendlich befinden, geht die Beziehung dank der wunderbaren Verknüpfungslog in Windows (man muss doch mal Windows und Microsoft loben) nicht verloren.

Gruß
evinben
Member: colinardo
colinardo Jun 25, 2014 updated at 16:37:31 (UTC)
Goto Top
Zitat von @evinben:
dann besteht aber das Problem mit der Pfadbeziehung. In einer Batch habe ich mit %~dp0
etwas ähnliches lässt sich auch mit der Verknüpfung erreichen:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -noexit -File ".\GetFileproperties.ps1"
Dann wird das Script immer im Pfad gesucht der in der Verknüpfung unter Ausführen in: steht.
Member: evinben
evinben Jun 25, 2014 updated at 19:19:12 (UTC)
Goto Top
jetzt verstehe ich, warum es bei mir bisher nie mit einer relativen Pfadeingabe in der Verknüpfung geklappt hat (mit ".\" bzw. "..\")! Weil mir nicht bewusst war, dass der Pfad in Ausführen in: Pflicht ist (dies habe ich nämlich bei Tests leider immer leer gelassen gehabt). Nun habe ich wieder was nützliches nebenbei gelernt. Aber hier nicht vergessen beschränkt sich der Vorteil der Beziehung lediglich nur bei Pfadänderungen innerhalb des Stammverzeichnisses.
In diesem Zusammenhang jedoch bleibt etwa wie %~dp0 auf Dauer deutlich robustere Variante (in einer Verknüpfung dagegen muss der Pfad bei einer Änderung des Stammverzeichnis jeweils zwangsweise angepasst werden).