Zurück zur Homepage

Dll - Exe - Treiber Infos

Manchmal wäre es schön, wenn man die Versionsnummer einer Dll oder Exe abfragen könnte. Im Explorer unter Schnellansicht geht das ja, aber aus einem Programm heraus? Die API-Funktion GetFileVersionInfo erledigt das. Wegen der leichteren Handhabung habe ich das hier in eine Klasse gepackt. Sie liefert Produktversion, Dateiart, Treibertyp, LanguageID, CompanyName, FileDescription, FileVersion, InternalName, LegalCopyright, OriginalFileName, Produktname und Zielsystem einer solchen Datei, soweit diese Informationen vorhanden sind.

Beispieldatei (dllinfos.zip 29 kB

'Anfang der Klasse clsDllInfo
Option Explicit
Private Declare Function GetFileVersionInfo _
  Lib "Version.dll" Alias "GetFileVersionInfoA" _
  (ByVal lptstrFilename As String, _
  ByVal dwhandle As Long, _
  ByVal dwlen As Long, _
  lpData As Any) As Long

Private Declare Function GetFileVersionInfoSize _
  Lib "Version.dll" _
  Alias "GetFileVersionInfoSizeA" _
  (ByVal lptstrFilename As String, _
  lpdwHandle As Long) As Long

Private Declare Function VerQueryValue Lib _
  "Version.dll" Alias "VerQueryValueA" _
  (pBlock As Any, ByVal lpSubBlock As String, _
  lplpBuffer As Any, puLen As Long) As Long

Private Declare Function GetSystemDirectory& _
  Lib "kernel32" Alias "GetSystemDirectoryA" _
  (ByVal lpBuffer As String, ByVal nSize As Long)

Private Declare Function lstrcpy Lib "kernel32" _
  Alias "lstrcpyA" (ByVal lpString1 As String, _
  ByVal lpString2 As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" _
  Alias "RtlMoveMemory" (dest As Any, _
  ByVal Source As Long, ByVal Length As Long)

Private Declare Sub CopyMemoryLongInteger Lib _
  "kernel32" Alias "RtlMoveMemory" _
  (dest As Long, Source As Integer, _
  ByVal Length As Long)

Private Declare Function GetFileAttributes Lib _
  "kernel32" Alias "GetFileAttributesA" _
  (ByVal lpFileName As String) As Long

Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Const FILE_ATTRIBUTE_HIDDEN = &H2
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const FILE_ATTRIBUTE_READONLY = &H1
Private Const FILE_ATTRIBUTE_SYSTEM = &H4
Private Const FILE_ATTRIBUTE_TEMPORARY = &H100
Private istrDateiname As String ' interne Variable des Dateipfades
Private istrProductVersion As String ' interne Variable der Version
Private istrDateiart As String ' interne Variable der Dateiart
Private istrTreibertyp As String ' interne Variable der Treiberart
Private istrLanguageID As String ' interne Variable der Language-ID
Private istrCompanyName As String ' interne Variable CompanyName
Private istrFileDescription As String ' interne Variable istrFileDescription
Private istrFileVersion As String ' interne Variable FileVersion
Private istrInternalName As String ' interne Variable InternalName
Private istrLegalCopyright As String ' interne Variable LegalCopyright
Private istrOriginalFileName As String ' interne Variable OriginalFileName
Private istrProductName As String ' interne Variable ProductName
Private istrZielsystem As String ' interne Variable Zielsystem  

Public Property Get ProductVersion() As String
  ProductVersion = istrProductVersion
End Property  

Public Property Get Filetype() As String
  Filetype = istrDateiart
End Property

Public Property Get Drivertype() As String
  Drivertype = istrTreibertyp
End Property

Public Property Get CompanyName() As String
  CompanyName = istrCompanyName
End Property

Public Property Get FileDescription() As String
  FileDescription = istrFileDescription
End Property

Public Property Get FileVersion() As String
  FileVersion = istrFileVersion
End Property

Public Property Get InternalName() As String
  InternalName = istrInternalName
End Property

Public Property Get LegalCopyright() As String
  LegalCopyright = istrLegalCopyright
End Property

Public Property Get OriginalFileName() As String
  OriginalFileName = istrOriginalFileName
End Property

Public Property Get ProductName() As String
  ProductName = istrProductName
End Property

 Public Property Get LanguageID() As String
  LanguageID = istrLanguageID
End Property

 Public Property Get Destinationsystem() As String
  Destinationsystem = istrZielsystem
End Property

 Private Sub resetten()
  'Variablen zurücksetzen
  istrZielsystem = ""
  istrLanguageID = ""
  istrProductName = ""
  istrOriginalFileName = ""
  istrLegalCopyright = ""
  istrInternalName = ""
  istrFileVersion = ""
  istrFileDescription = ""
  istrCompanyName = ""
  istrTreibertyp = ""
  istrDateiart = ""
  istrProductVersion = ""
  istrDateiname = ""
End Sub

Private Sub Versionsinfos()
  Dim arrInfo() As Byte
  Dim strBuffer As String
  Dim lngZielsystem As Long
  Dim lngInfoLänge As Long
  Dim lngVersionPointer As Long
  Dim lngSprache As Long
  Dim strInfotyp As String
  Dim intSprache(1 To 3) As Integer
  Dim lngZähler As Long
  Dim lngDateityp As Long, lngSubtyp As Long
  'Die benötigte Bufferlänge wird ermittelt
  lngInfoLänge = GetFileVersionInfoSize(istrDateiname, 0&)
  'Wenn keine Info vorhanden ist, beenden
  If lngInfoLänge = 0 Then
    istrDateiname = ""
    Exit Sub
  End If
  'Der Buffer wird entsprechend dimensioniert
  ReDim arrInfo(lngInfoLänge)
  'Der Buffer wird gefüll
  GetFileVersionInfo istrDateiname, 0&, _
    lngInfoLänge, arrInfo(0)
  '********************************************************************
  '***** Hier beginnt der allgemeine Teil, unabhängig
  '***** von der Sprachversion
  '********************************************************************
  'Pointer zur Wurzel der Infostruktur
  VerQueryValue arrInfo(0), "\", lngVersionPointer, 0
  'An der richtigen Pos. (+32) das Zielsystem lesen
  'lt. Datentyp VS_FIXEDFILEINFO
  CopyMemory lngZielsystem, (lngVersionPointer + 32), 4
  'An der richtigen Pos. (+36) den Dateityp lesen
  'lt. Datentyp VS_FIXEDFILEINFO
  CopyMemory lngDateityp, (lngVersionPointer + 36), 4
  'An der richtigen Pos. (+40) den Subtyp lesen
  'lt. Datentyp VS_FIXEDFILEINFO
  CopyMemory lngSubtyp, (lngVersionPointer + 40), 4
  'Auswertung des Zielsystems
  Select Case lngZielsystem
    Case &H10001
      istrZielsystem = "DOS/Win16"
    Case &H10004
      istrZielsystem = "DOS/Win32"
    Case &H40004
      istrZielsystem = "NT/Win32"
    Case Else
      istrZielsystem = "Keine Angabe"
  End Select
  'Auswertung des Dateityps
  Select Case lngDateityp
    Case &H1
      istrDateiart = "EXE"
    Case &H2
      istrDateiart = "DLL"
    Case &H3
      istrDateiart = "Treiber"
      'Wenn Treiber, dann den Subtyp auswerten
      Select Case lngSubtyp
        Case &H1
          istrTreibertyp = "Drucker"
        Case &H2
          istrTreibertyp = "Tastatur"
        Case &H3
          istrTreibertyp = "Sprache"
        Case &H4
          istrTreibertyp = "Monitor"
        Case &H5
          istrTreibertyp = "Maus"
        Case &H6
          istrTreibertyp = "Netzwerk"
        Case &H7
          istrTreibertyp = "System"
        Case &H9
          istrTreibertyp = "Sound"
        Case &HA
          istrTreibertyp = "Comm"
      End Select
      Case &H4
        istrDateiart = "Font"
      Case &H5
        istrDateiart = "Virtueller Gerätetreiber"
      Case &H7
        istrDateiart = "Lib"
      Case Else
        istrDateiart = "Andere"
    End Select
    'Zeiger zur Sprachversion ermitteln
    VerQueryValue arrInfo(0), _
      "\VarFileInfo\Translation", _
      lngVersionPointer, lngInfoLänge
     'Werte ab dieser Speicheradresse lesen.
     'Hier zwei Integer (4 Byte)
     CopyMemory intSprache(1), lngVersionPointer, 4
    'Reihenfolge Lo and Hi tauschen
     intSprache(3) = intSprache(1) 'intSprache(3) als Zwischenspeicher
     intSprache(1) = intSprache(2)
     intSprache(2) = intSprache(3)
    'In Datentyp Long umwandeln
    CopyMemoryLongInteger lngSprache, _
      intSprache(1), 4
    'Hexdarstellung
    istrLanguageID = Hex(lngSprache)
    'Führende Nullen hinzu
    istrLanguageID = String(8 - Len(istrLanguageID), _
      Asc("0")) & istrLanguageID
  '********************************************************************
  '***** Hier beginnt der Sprachspezifische Teil
  '***** StringFileInfo
  '********************************************************************
  For lngZähler = 1 To 8
  strBuffer = String(255, 0)
  'Der Abfragestring wird je nach Wert zähler
  'erzeugt.
  strInfotyp = "\StringFileInfo\" & _
    istrLanguageID & "\"
  Select Case lngZähler
    Case 1
      strInfotyp = strInfotyp _
        & "CompanyName"
    Case 2
      strInfotyp = strInfotyp _
        & "FileDescription"
    Case 3
      strInfotyp = strInfotyp _
        & "FileVersion"
    Case 4
      strInfotyp = strInfotyp _
        & "InternalName"
    Case 5
      strInfotyp = strInfotyp _
        & "LegalCopyright"
    Case 6
      strInfotyp = strInfotyp _
        & "OriginalFileName"
    Case 7
      strInfotyp = strInfotyp _
        & "ProductName"
    Case 8
      strInfotyp = strInfotyp _
        & "ProductVersion"
  End Select
  'Ein Pointer auf die gewünschte Info
  'wird zurückgeliefert
  VerQueryValue arrInfo(0), strInfotyp, _
    lngVersionPointer, lngInfoLänge
  'Der Buffer wird mit dem String ab der
  'Speicheradresse lngVersionPointer gefüllt
  lstrcpy strBuffer, lngVersionPointer
  'Zurückstutzen auf die richtige Länge
  strBuffer = Mid$(strBuffer, 1, _
    InStr(strBuffer, Chr(0)) - 1)
  'Variablen mit gewünschter Info füllen
  Select Case lngZähler
    Case 1
      istrCompanyName = strBuffer
    Case 2
      istrFileDescription = strBuffer
    Case 3
      istrFileVersion = strBuffer
    Case 4
      istrInternalName = strBuffer
    Case 5
      istrLegalCopyright = strBuffer
    Case 6
      istrOriginalFileName = strBuffer
    Case 7
      istrProductName = strBuffer
    Case 8
      istrProductVersion = strBuffer
  End Select
  Next
End Sub

Public Property Get Dateiname() As String
  Dateiname = istrDateiname
End Property

Public Property Let Dateiname(ByVal vNewValue As String)
  Dim SysDir As String
  Call resetten 'Alle Variablen zurücksetzen
  'Dir$ wird nicht verwendet, da Dir$ keine Rekursion unterstützt
  'und eventuell ein Dir$ in der aufrufenden Prozedur stört.
  '(Hab aber nicht getestet, ob das stört)
  If GetFileAttributes(vNewValue) <> -1 Then
    'Datei existiert
    istrDateiname = vNewValue
  Else
    'Datei existiert nicht. Den Systempfad voranstellen
    SysDir = String(256, 0)
    GetSystemDirectory SysDir, 255
    SysDir = Left$(SysDir, _
    InStr(1, SysDir, Chr(0)) - 1)
    If GetFileAttributes(SysDir & "\" & vNewValue) <> -1 Then
      'Jetzt existiert Datei.
      istrDateiname = SysDir & "\" & vNewValue
    End If
  End If
  'Wenn die Variable istrDateiname leer ist wird das Aufrufen
  'der Prozedur Versionsinfos verhindert
  If istrDateiname <> "" Then
    If GetFileAttributes(istrDateiname) <> _
      FILE_ATTRIBUTE_DIRECTORY Then
      'istrDateiname darf kein Directory sein, es macht
      'keinen Sinn Versionsinfos eines Verzeichnisses
      'zu ermitteln
      Versionsinfos
    Else
      istrDateiname = ""
    End If
  End If
End Property
'Ende der Klasse 
'#########################################################
'Code zum Testen der Klasse
Option Explicit

Dim Infoklasse As clsDllInfo
Public Sub DLLInfos()
  Dim Meldung As String, Datei As String
  Dim i As Long
  Set Infoklasse = New clsDllInfo
  'GetFileOpen siehe Beispielcode Nr. 6
  'oder Application.GetOpenFileName
  Datei = GetFileOpen("c:\", "dll", "Dateiinfos auflisten")
  If Datei = "" Then Exit Sub
  With Infoklasse
    .Dateiname = Datei
    If .Dateiname = "" Then Exit Sub
    Meldung = Meldung & "Datei Name= " & .Dateiname & vbCrLf
    Meldung = Meldung & "Company Name= " & .CompanyName & vbCrLf
    Meldung = Meldung & "Filetype= " & .Filetype & vbCrLf
    Meldung = Meldung & "Zielsystem= " & .Destinationsystem & vbCrLf
    Meldung = Meldung & "Treibertyp= " & .Drivertype & vbCrLf
    Meldung = Meldung & "Beschreibung= " & .FileDescription & vbCrLf
    Meldung = Meldung & "Version= " & .FileVersion & vbCrLf
    Meldung = Meldung & "Interner Name= " & .InternalName & vbCrLf
    Meldung = Meldung & "Sprache= " & .LanguageID & vbCrLf
    Meldung = Meldung & "Copyright= " & .LegalCopyright & vbCrLf
    Meldung = Meldung & "Orginalname= " & .OriginalFileName & vbCrLf
    Meldung = Meldung & "Produktname= " & .ProductName & vbCrLf
    Meldung = Meldung & "Produktversion= " & .ProductVersion
  End With
  MsgBox Meldung
End Sub