tegwert
Goto Top

Per Batch Produktversion auslesen

Hallo zusammen!

Ich nutze folgendes Script von bastla aus einem Beitrag des Forums (Versionsnummer von OCX per batch auslesen und drucken&thread=true#jump_comments) um die Dateiversion einer EXE-Datei auszulesen:

@echo off & setlocal
set "Datei=c:\temp\firefox.exe"  
set "GetV=%Temp%\GetV.vbs"  
echo Set objWMIService=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")>"%GetV%"  
echo Set colFiles=objWMIService.ExecQuery ("SELECT * FROM CIM_Datafile WHERE Name='"^&Replace(WScript.Arguments(0),"\","\\")^&"'")>>"%GetV%"  
echo For Each objFile in colFiles: WScript.Echo objFile.version: Next>>"%GetV%"  
set Version=
for /f %%i in ('cscript //nologo "%GetV%" "%Datei%"') do set "Version=%%i"  
if defined Version echo %Datei% - Version %Version%
del "%GetV%"  
pause

Das Script funktioniert soweit auch ohne Probleme und gibt mir die Dateiversion "6.0.0.4144" aus. Soweit so gut.
Nun gibt es aber in den Dateieigenschaften dieser EXE-Datei noch eine "Produktversion":

ecac57ce9a08cac2f94cf98fffd9094c

Wie muss ich das Script anpassen, damit nun diese "Produktversion" ausgelesen wird? Oder gibt es dafür noch eine andere Lösung?

Für Eure Hilfe bedanke ich mich bereits im voraus!

Gruß
tegwert

Content-ID: 165865

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

Ausgedruckt am: 26.11.2024 um 01:11 Uhr

Biber
Biber 08.05.2011 um 18:51:27 Uhr
Goto Top
Moin tegwert,

vorbehaltlich einem möglichen Veto seitens bastla würde ich behaupten, dass du die "Produktversion" nicht über die oben verwendete Strategie ermitteln kannst.
Denn diese Infos bekommst du eher über das Shell.Application-Object und den Namespace des folders als über die File-Attribute.

Ein Schnellschuss wäre:
'GetFileDetailInfos.vbs  
' inspiriert von http://stackoverflow.com/questions/2976734/how-to-retrieve-a-files-product-version-in-vbscript  
Dim objShell, objFolder, objFolderItem, i, j 

Set FSO=CreateObject("Scripting.FileSystemObject")  
If Wscript.Arguments.Count > 0 then
  sFullFileName = Wscript.Arguments(0)
Else
    sFullFileName ="c:\temp\firefox.exe"  
End if  
If FSO.FileExists(sFullFileName) Then
    sFilePath= FSO.GetParentFolderName(sFullFileName)
    sProgram = FSO.GetFileName(sFullFileName)
    Set objShell = CreateObject("Shell.Application")  
    Set objFolder = objShell.Namespace(sFilePath)
    Set objFolderItem = objFolder.ParseName(sProgram)
    Dim arrHeaders(300)
    For i = 0 To 300
        arrHeaders(i) = objFolder.GetDetailsOf(objFolder.Items, i)
      ' WScript.Echo i &"- " & arrHeaders(i) & ": " & objFolder.GetDetailsOf(objFolderItem, i)  
        If lcase(arrHeaders(i))= "dateiversion" Then  
            WScript.Echo arrHeaders(i) & ": " & objFolder.GetDetailsOf(objFolderItem, i)  
            j=j+1
        End If

        If lcase(arrHeaders(i))= "produktversion" Then  
            WScript.Echo arrHeaders(i) & ": " & objFolder.GetDetailsOf(objFolderItem, i)  
            j=j+1
        End if
        If (j = 2) then
          Exit For
        End If
    Next
End If

Ausgabe von meinem CMD-Prompt aus
>f:\schnipsel\getFileDetailInfos.vbs
Dateiversion: 2.0.1.4120
Produktversion: 4.0.1.0

Grüße
Biber
bastla
bastla 08.05.2011 um 19:16:06 Uhr
Goto Top
@Biber
Keinerlei Einwand face-wink, aber als Hinweis: für XP wäre (lt dieser Auflistung) der Direktzugriff über Property 39 und für Vista über 252 264 (siehe nächster Kommentar) möglich; für W7 ergibt sich unter Verwendung des von Dir geposteten Scripts 268

Unter XP hatte ich jedenfalls mit der folgenden "Kurzform" (Übergabe des Dateipfades als Parameter) Erfolg:
Set fso = CreateObject("Scripting.FileSystemObject")  
Set objShell = CreateObject("Shell.Application")  
strFilePath = WScript.Arguments(0)
Set objFolder = objShell.Namespace(fso.GetParentFolderName(strFilePath))
strLookFor = LCase(fso.GetFileName(strFilePath))

For Each strFileName in objFolder.Items
    strName = objFolder.GetDetailsOf(strFileName, 0)
    If LCase(strName) = strLookFor Then WScript.Echo objFolder.GetDetailsOf(strFileName, 39)
Next
[Edit] Die Version für W7:
Set fso = CreateObject("Scripting.FileSystemObject")  
Set objShell = CreateObject("Shell.Application")  
strFilePath = WScript.Arguments(0)
Set objFolder = objShell.Namespace(fso.GetParentFolderName(strFilePath))
strLookFor = LCase(fso.GetBaseName(strFilePath))

For Each strFileName in objFolder.Items
    strName = objFolder.GetDetailsOf(strFileName, 0)
    If LCase(strName) = strLookFor Then WScript.Echo objFolder.GetDetailsOf(strFileName, 268)
Next
Ich musste neben der Änderung von 39 auf 268 auch (siehe Zeile 5) den Dateinamen ohne Extension (="BaseName") für die Suche verwenden [Edit2] ... aber nur, weil in den Explorer-Einstellungen die Anzeige der Dateitypen ausgeblendet war - ein Argument mehr für die verbesserten Versionen unten von rubberman und Biber [/Edit2] ...
[/Edit]

Grüße
bastla
Biber
Biber 08.05.2011, aktualisiert am 01.08.2013 um 18:47:30 Uhr
Goto Top
Moin bastla,

wir hatten ja schon irgendwann mal über die ganze (je nach Sichtweise) Weltoffenheit/Flexbilität/Beliebigkeit/Wackligkeit der Durchnummerierung dieser Extended File Attributes geplaudert.

Was immer die RedmonderInnen dazu getrieben haben mag - ich sach mal so:
eigentlich werden schon mal zwei Hubschrauber und ein paas Marines aus nichtigeren Anlässen losgeschickt.

Diese vermeintlich "festen" versionsabhängigen Detailattribute haben eine noch kürzere Halbwertszeit als FDP-Parteitagsbeschlüsse,

Unter meinem Vista-Notebook kommt heraus
Attribut #252- Zweikanalton

Die beiden abgefragten Attribute:
156- Dateiversion: 2.0.1.4120
264- Produktversion: 4.0.1.0

Soweit zum Thema Praktikanten und Leisten. face-wink

Einziger mildernder Umstand für die Mädels: Okay, WhoTF sollte auch jemals so ein überflüssiges Attribut auslesen wollen?
@tegwert: Wofür brauchst du denn sowas??

Grüße
Biber
bastla
bastla 08.05.2011 um 19:48:33 Uhr
Goto Top
Hallo Biber!
eine noch kürzere Halbwertszeit als FDP-Parteitagsbeschlüsse
XP hält sich in dieser Hinsicht zumindest ganz gut; was den Rest angeht: schaun mer mal ...

Grüße
bastla
rubberman
rubberman 08.05.2011 um 19:57:08 Uhr
Goto Top
Hallo Zusammen.

Warum das Kind nicht beim Namen nennen: "productversion"

In einem Paralleluniversum habe ich dem TO vorhin folgenden Vorschlag unterbreitet:
@echo off &setlocal
set "Datei=C:\Program Files\Mozilla Firefox\Firefox.exe"  
(
  echo Set objFSO = CreateObject^("Scripting.FileSystemObject"^)  
  echo Set objShell = CreateObject^("Shell.Application"^)  
  echo Set objFolder = objShell.NameSpace^(objFSO.GetParentFolderName^(WScript.Arguments^(0^)^)^)
  echo WScript.Echo objFolder.ParseName^(objFSO.GetFileName^(WScript.Arguments^(0^)^)^).ExtendedProperty^("productversion"^)  
)>"%temp%\getPV.vbs"  

for /f %%i in ('cscript //nologo "%temp%\getPV.vbs" "%Datei%"') do set "ProdVersion=%%i"  
del "%temp%\getPV.vbs"  
if defined ProdVersion echo %Datei% - ProduktVersion %ProdVersion%

pause

Grüße
rubberman
Biber
Biber 08.05.2011 um 20:00:21 Uhr
Goto Top
Moin bastla,

Zitat von @bastla:
> eine noch kürzere Halbwertszeit als FDP-Parteitagsbeschlüsse
XP hält sich in dieser Hinsicht zumindest ganz gut; was den Rest angeht: schaun mer mal ...
Du kannst doch nicht die FDP mit einem bewährten und stabilen Erfolgsmodell wie XP vergleichen.
Ich schrieb doch " bei Vista..." face-wink

Grüße
Biber

[Edit] @rubberman
Okay, so ist es viel schlanker - aber wie kamst du jetzt von "FDP-Parteitagsbeschlüssen" auf "in einem Paralleluniversum"?
Ketzer face-wink

Meine jetzt eingedampfte V2-Version sieht mit Abfrage von"Productversion" und "Fileversion" dann fast wie deine aus:
'GetFileDetailInfosV2.vbs  
Set FSO=CreateObject("Scripting.FileSystemObject")  
If Wscript.Arguments.Count > 0 then
    sFullFileName = Wscript.Arguments(0)
Else
    sFullFileName ="C:\Program Files\Mozilla Firefox\firefox.exe"  
End if  
If FSO.FileExists(sFullFileName) Then
    Set objFolder = CreateObject("Shell.Application").Namespace(FSO.GetParentFolderName(sFullFileName))  
    Set objFolderItem = objFolder.ParseName(FSO.GetFileName(sFullFileName))
    WScript.Echo "Datei Version  : " & objFolderItem.ExtendedProperty("Fileversion")  
    WScript.Echo "Produkt Version: " & objFolderItem.ExtendedProperty("productversion")  
End If
Ausgabe
>f:\schnipsel\getFileDetailInfosV2.vbs
Datei Version  : 2.0.1.4120
Produkt Version: 4.0.1.0

[/Edit]
tegwert
tegwert 08.05.2011 um 20:26:41 Uhr
Goto Top
Hallo zusammen!

Vielen Dank an alle für die schnellen Lösungsvorschläge!

Gruß
tegwert
bastla
bastla 08.05.2011 um 21:38:20 Uhr
Goto Top
Hallo rubberman!

Sehr schöne Lösung face-smile

- nur wäre mir die verringerte Lesbarkeit durch das "Escapen" der Klammern ein zu hoher Preis für das "Auf einen Rutsch in die Datei schreiben"-Feature (ist aber natürlich sehr subjektiv) ...

Grüße
bastla
ovu-p86
ovu-p86 10.05.2011 um 03:31:19 Uhr
Goto Top
Hallo Biber, Hallo Rubberman,

sowas hab ich schon lange gesucht.
Wie kann man das umbauen, daß die Programme aus eine .txt-Datei eingelesen werden.

Wofür ist das, Was soll erreicht werden:
Ein System auf die Aktualität der wichtigsten, grundlegenden Programme prüfen. Die gewünschten, zu überprüfenden Progamme stehen in einer "progr.txt".

progr.txt
C:\Programme\Adobe\Reader 9.0\Reader\AcroRd32.exe
C:\Programme\Java\jre6\bin\java.exe
C:\WINDOWS\SYSTEM32\Macromed\Flash\FlashUtil10p_Plugin.exe
u.s.w.

Nun kann es natürlich sein, daß ein Programm auf einem System nicht vorhanden ist. Das müßte dann abgefangen werden damit das Ganze nicht abbricht.

Was ich an Bibers Lösung angenehm finde ist, das beides, Datei und Produkt-Version abgefragt werden.
(Oft gibts ja keinen Eintrag unter Produkt-Version, Datei-Version aber immer.)
Wäre schön wenn das Ergebnis dann in einer .txt-Datei landet.

Könnt ihr da noch mal weiterhelfen? Denke ist auch für viele andere interessant. Wäre dann richtig universell einsetzbar.

(Ums noch universeller zu machen, die "progr.txt" nicht so statisch zu lassen, würde ich dann versuchen nach den jeweiligen Programmen mit ggf. individuellen Programmpfaden oder Windows-Versionen zu suchen. Allerdings auf cmd-Basis, also vorgeschalteteten cmd der die "progr.txt" individuell erzeugt.)


Danke, Gruß
Uwe
Biber
Biber 10.05.2011, aktualisiert am 01.08.2013 um 18:29:04 Uhr
Goto Top
Moin ovu-p86,

wenn ich von meiner "v2"-Version aus dem Vorkommentar ausgehe, sind nur banale Anpassungen nötig - eigentlich sollte nur zusätzlich des als "Parameter1" übergebenen Programms mit ausgegeben werden. Bedeutet eine zusätzliche Zeile Schreibaufwand.

'GetFileDetailInfosV2fürMassenverarbeitung.vbs  
Set FSO=CreateObject("Scripting.FileSystemObject")  
If Wscript.Arguments.Count > 0 then
    sFullFileName = Wscript.Arguments(0)
Else
    sFullFileName ="C:\Program Files\Mozilla Firefox\firefox.exe"  
End if  
If FSO.FileExists(sFullFileName) Then
    Wscript.echo "[" & sFullFileName & "]"  
    Set objFolder = CreateObject("Shell.Application").Namespace(FSO.GetParentFolderName(sFullFileName))  
    Set objFolderItem = objFolder.ParseName(FSO.GetFileName(sFullFileName))
    WScript.Echo "Datei Version  : " & objFolderItem.ExtendedProperty("Fileversion")  
    WScript.Echo "Produkt Version: " & objFolderItem.ExtendedProperty("productversion")  
End If
[ungetestet - neu ist nur Zeile 09]

Der Aufruf mit der "alleGefragtenExeDateien.txt" kann dann ja in einer FOR/F-Anweisung erfolgen.
FOR /F %i "delims=" %i in ('X:\Doku\alleGefragtenExeDateien.txt') do X:\whereEver\GetFileDetailInfosV2fürMassenverarbeitung.vbs "%~i"

Grüße
Biber

[Edit 11.5. Tippfehler Zeile 09]
alt : Wscript.echo "[" & sFullFileName % "]"
neuer: Wscript.echo "[" & sFullFileName & "]"
[/Edit 11.5. Tippfehler Zeile 09]
rubberman
rubberman 10.05.2011 um 20:16:35 Uhr
Goto Top
Hallo ovu-p86, Moin Biber.

Als Stand-Alone-VBScript würde ich es so lösen:
strSourceFile = "progr.txt"  
strDestFile = "Versions.csv"  

Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")  
If Not objFSO.FileExists(strSourceFile) Then WScript.Quit 1
Dim objShell : Set objShell = CreateObject("Shell.Application")  

Set objSourceFile = objFSO.OpenTextFile(strSourceFile, 1)
Set objDestFile = objFSO.OpenTextFile(strDestFile, 2, True)
objDestFile.WriteLine("Programm;Dateiversion;Produktversion;Gefunden")  
Do While Not objSourceFile.AtEndOfStream
  strLine = Trim(objSourceFile.ReadLine)
  arrVersions = GetFileDetailInfos(strLine)
  If VarType(arrVersions) = vbEmpty Then
    objDestFile.WriteLine(strLine & ";;;" & False)  
  Else
    objDestFile.WriteLine(strLine & ";" & arrVersions(0) & ";" & arrVersions(1) & ";" & True)  
  End If
Loop
objDestFile.Close
objSourceFile.Close

Function GetFileDetailInfos(strFileFullName)
  Dim arrVer(1)
  If objFSO.FileExists(strFileFullName) Then
    Set objFolderItem = objShell.Namespace(objFSO.GetParentFolderName(strFileFullName)) _ 
      .ParseName(objFSO.GetFileName(strFileFullName))
    arrVer(0) = objFolderItem.ExtendedProperty("FileVersion")  
    arrVer(1) = objFolderItem.ExtendedProperty("ProductVersion")  
    GetFileDetailInfos = arrVer
  End If
End Function

Grüße
rubberman
ovu-p86
ovu-p86 10.05.2011 um 22:28:08 Uhr
Goto Top
Hallo Biber, hallo rubberman,

Danke für die Lösungen.

Hatte heut nachmittag mal Bibers Lösung probiert. Hatte aber immer Fehlermeldungen. Habs versucht zu ändern, aber nicht hingekriegt. Wahrscheinlich wieder irgendein " , oder was weiß ich.

Eben habe ich Rubbermans Lösung probiert. Haut auf Anhieb hin. Auch nicht existierende Programme aus "progr.txt" werden abgefangen. Klasse. Danke.

Werde jetzt mal versuchen die "progr.txt" Erzeugung individueller zu gestalten.

Gruß
Uwe
ovu-p86
ovu-p86 11.05.2011 um 11:08:43 Uhr
Goto Top
Hallo,


hier jetzt der cmd um die "progr.txt" variabler zu handeln.
Falls man das Ganze mal auf einem anderen Rechner und Betriebssystem nutzt funktioniert das Ganze
immer noch. Die für das eigene System erstellte "progr.txt" dient dann als Anhaltspunkt.

Der cmd prüft ob die in progr.txt stehenden Programmpfade stimmen.
Wenn nicht wird eine Suche ausgelöst. Das Ganze wird dann in "progr_indiv.txt" geschrieben die anschließend
an den vbs übergeben. Der cmd selber ist Leerzeichenresistent.


Das Ganze ist natürlich nicht ideal, die Suche auf fremden Systemen dauert natürlich umso länger je weniger
Übereinstimmungen mit dem eigenen System bestehen. Aber es ist bei Bedarf eben universell.

Wie benutzen?
1. "progr.txt" mit der Liste der abzufragenden Programme erstellen.
2. "VersionFinder.cmd","rubberman.vbs" und "progr.txt" zusammen in ein beliebiges Verzeichnis kopieren.

Jetzt können durch Aufruf des "VersionFinder.cmd" die Datei- und Produktversion ermittelt werden.
Geht auch vom USB-Stick.


progr.txt (Beispiel)
C:\Programme\Adobe\Reader 9.0\Reader\AcroRd32.exe
C:\Programme\Java\jre6\bin\java.exe
C:\WINDOWS\SYSTEM32\Macromed\Flash\FlashUtil10p_Plugin.exe
D:\Eigene Dateien\_versch\__progr\ThunderbirdPortable_\App\Thunderbird\thunderbird.exe
u.s.w.


VersonsFinder.cmd
@echo off
rem ______________________________________________________________________________________________________
rem . Datei und Produkt-Version ausgewaehlter Programme anzeigen
rem ---------------------------------------------------------------------------------------------------
rem . Diesen cmd, rubberman.vbs und progr.txt in ein beliebiges Verzeichnis kopieren und von dort aufrufen
rem . In der progr.txt die gewuenschten, abzufragenden Programme eintragen
rem ______________________________________________________________________________________________________

:setting
rem ++++++++ Hier bei Bedarf die max. abzusuchenden Lfw eingeben ++++++++++++
set lfw=c d

rem ++++++++ Name und Typ der Ausgabedatei, ggf. aendern ++++++++++++++++++++
set ausgabe=VersionsInfo.txt
rem ______________________________________________________________________________________________________

:aktion
set cmdpfad=%~dp0
set "suche=%cmdpfad%progr.txt"  
set source=progr_indiv.txt
if exist "%cmdpfad%%source%" del "%cmdpfad%%source%"  

FOR /F "usebackq delims=" %%a in ("%suche%") do if exist "%%a" (echo %%a >>"%cmdpfad%%source%") ELSE (for %%i in (%lfw%) do cd /d %%i:\ & dir "%%~nxa" /s /b >>"%cmdpfad%%source%")  

cd /d "%cmdpfad%" & "rubberman.vbs" "%source%" "%ausgabe%"  

:extra
if %ausgabe:~-3% EQU txt notepad "%cmdpfad%%ausgabe%"  


rubberman.vbs
' vbs made by rubberman  
strSourceFile = WScript.Arguments(0)
strDestFile = WScript.Arguments(1)

Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")  
If Not objFSO.FileExists(strSourceFile) Then WScript.Quit 1
Dim objShell : Set objShell = CreateObject("Shell.Application")  

Set objSourceFile = objFSO.OpenTextFile(strSourceFile, 1)
Set objDestFile = objFSO.OpenTextFile(strDestFile, 2, True)
objDestFile.WriteLine("Programm;Dateiversion;Produktversion;Gefunden")  
Do While Not objSourceFile.AtEndOfStream
  strLine = Trim(objSourceFile.ReadLine)
  arrVersions = GetFileDetailInfos(strLine)
  If VarType(arrVersions) = vbEmpty Then
    objDestFile.WriteLine(strLine & ";;;" & False)  
  Else
    objDestFile.WriteLine(strLine & ";" & arrVersions(0) & ";" & arrVersions(1) & ";" & True)  
  End If
Loop
objDestFile.Close
objSourceFile.Close

Function GetFileDetailInfos(strFileFullName)
  Dim arrVer(1)
  If objFSO.FileExists(strFileFullName) Then
    Set objFolderItem = objShell.Namespace(objFSO.GetParentFolderName(strFileFullName)) _ 
      .ParseName(objFSO.GetFileName(strFileFullName))
    arrVer(0) = objFolderItem.ExtendedProperty("FileVersion")  
    arrVer(1) = objFolderItem.ExtendedProperty("ProductVersion")  
    GetFileDetailInfos = arrVer
  End If
End Function


An der Formatierung der Ausgabe könnte man natürlich noch was machen.
Vielleicht ist es doch besser das Ganze als .csv auszugeben und mit Excel o.ä. öffnen.
Aber kann man ja im cmd ändern statt VersionsInfo.txt eben .csv

Gruß
Uwe
Biber
Biber 11.05.2011 um 20:05:15 Uhr
Goto Top
Moin ovu.p86,

Nachtrag.
Auch wenn es nicht mehr so interessant ist, weil du eine Lösung fertig hast - ich habe eben noch mal die neue Zeile09 in meinem letzten Kommentar angeschaut.
Da hatte ich irgendwo -so etwas ist selbst bei nur einer einzigen neuen Zeile möglich- einen albernen Tippfehler eingebaut.

Siehe oben.

Grüße
Biber
mfritsch
mfritsch 13.07.2011 um 08:52:02 Uhr
Goto Top
Hallo,

kann mir vielleicht jemand helfen.

Das script funktioniert eigentlich ganz gut, aber warum wird bei mir unter XP immer Version "null" ausgegeben??
Unter Win7 gehts problemlos.

Was muss an dem Script angepasst werden, damit es bei beiden OS funktioniert?

Gruß