Page 1 of 1

GetFileVersionInfo

Posted: Tue May 25, 2010 3:38 pm
by akee
Credits to http://www.purebasic.fr/english/viewtopic.php?t=13910.

Playing with this and decided to share with the community... Cut and paste code to test.pb in the C:\TEMP folder. Change the version info in Compiler/Compiler Options/Version Info. Create an executable test.exe and run the program. Change the values to suit your taste.

Code: Select all

Enumeration
  #FVI_FileVersion      = $0001
  #FVI_FileDescription  = $0002
  #FVI_LegalCopyright   = $0004
  #FVI_InternalName     = $0008
  #FVI_OriginalFilename = $0010
  #FVI_ProductName      = $0020
  #FVI_ProductVersion   = $0040
  #FVI_CompanyName      = $0080
  #FVI_LegalTrademarks  = $0100
  #FVI_SpecialBuild     = $0200
  #FVI_PrivateBuild     = $0400
  #FVI_Comments         = $0800
  #FVI_Language         = $1000
  #FVI_Email            = $1001
  #FVI_Website          = $1002
  #FVI_Special          = $1003
EndEnumeration

Procedure.s GetFileVersionInfo_ElementName(ElementFlag)
  Protected TempString$ = ""
  Select ElementFlag
    Case #FVI_FileVersion
      TempString$ = "FileVersion"
    Case #FVI_FileDescription
      TempString$ = "FileDescription"
    Case #FVI_LegalCopyright
      TempString$ = "LegalCopyright"
    Case #FVI_InternalName
      TempString$ = "InternalName"
    Case #FVI_OriginalFilename
      TempString$ = "OriginalFilename"
    Case #FVI_ProductName
      TempString$ = "ProductName"
    Case #FVI_ProductVersion
      TempString$ = "ProductVersion"
    Case #FVI_CompanyName
      TempString$ = "CompanyName"
    Case #FVI_LegalTrademarks
      TempString$ = "LegalTrademarks"
    Case #FVI_SpecialBuild
      TempString$ = "SpecialBuild"
    Case #FVI_PrivateBuild
      TempString$ = "PrivateBuild"
    Case #FVI_Comments
      TempString$ = "Comments"
    Case #FVI_Language
      TempString$ = "Language"
    Case #FVI_Email
      TempString$ = "Email"
    Case #FVI_Website
      TempString$ = "Website"
    Case #FVI_Special
      TempString$ = "Special"
  EndSelect
  ProcedureReturn TempString$
EndProcedure

CompilerIf #PB_Compiler_Unicode
  Prototype.l GetFileVersionInfoSizeW(lptstrFilename.p-unicode, lpdwHandle.l)
  Prototype.l GetFileVersionInfoW(lptstrFilename.p-unicode, dwHandle.l, dwLen.l, lpData.l)
  Prototype.l VerQueryValueW(pBlock.l, lpSubBlock.p-unicode, lplpBuffer.l, puLen.w)
  Prototype.l VerLanguageNameW(wLang.l, szLang.p-unicode, cchLang.l)
CompilerElse
  Prototype.l GetFileVersionInfoSizeA(lptstrFilename.p-ascii, lpdwHandle.l)
  Prototype.l GetFileVersionInfoA(lptstrFilename.p-ascii, dwHandle.l, dwLen.l, lpData.l)
  Prototype.l VerQueryValueA(pBlock.l, lpSubBlock.p-ascii, lplpBuffer.l, puLen.w)
  Prototype.l VerLanguageNameA(wLang.l, szLang.p-ascii, cchLang.l)
CompilerEndIf

Procedure.s GetFileVersionInfoString(lptstrFilename$, FVI_Flag)
  Protected TempString$ = "", TempPtr, TempBlkSize, *TempBlk
  Protected TempLibHandle, TempBuff, TempBuffSize, TempCPLI$, TempLangSize = 128, TempLang$ = Space(TempLangSize)
  
  If FileSize(lptstrFilename$) >= 0
    TempLibHandle = OpenLibrary(#PB_Any, "version.dll")
    If TempLibHandle
      CompilerIf #PB_Compiler_Unicode
        GetFileVersionInfoSize.GetFileVersionInfoSizeW = GetFunction(TempLibHandle, "GetFileVersionInfoSizeW")
        GetFileVersionInfo.GetFileVersionInfoW = GetFunction(TempLibHandle, "GetFileVersionInfoW")
        VerQueryValue.VerQueryValueW = GetFunction(TempLibHandle, "VerQueryValueW")
        VerLanguageName.VerLanguageNameW = GetFunction(TempLibHandle, "VerLanguageNameW")
      CompilerElse
        GetFileVersionInfoSize.GetFileVersionInfoSizeA = GetFunction(TempLibHandle, "GetFileVersionInfoSizeA")
        GetFileVersionInfo.GetFileVersionInfoA = GetFunction(TempLibHandle, "GetFileVersionInfoA")
        VerQueryValue.VerQueryValueA = GetFunction(TempLibHandle, "VerQueryValueA")
        VerLanguageName.VerLanguageNameA = GetFunction(TempLibHandle, "VerLanguageNameA")
      CompilerEndIf

      TempBlkSize = GetFileVersionInfoSize(lptstrFilename$, @TempPtr)
      If TempBlkSize > 0
        *TempBlk = AllocateMemory(TempBlkSize)
        If *TempBlk > 0
          If GetFileVersionInfo(lptstrFilename$, 0, TempBlkSize, *TempBlk)
            If VerQueryValue(*TempBlk, "\\VarFileInfo\\Translation", @TempBuff, @TempBuffSize)
              TempCPLI$ = RSet(Hex(PeekW(TempBuff)), 4, "0") + RSet(Hex(PeekW(TempBuff + 2)), 4, "0")
              VerLanguageName(PeekW(TempBuff), TempLang$, TempLangSize)
            EndIf 
            If VerQueryValue(*TempBlk, "\\StringFileInfo\\" + TempCPLI$ + "\\" + GetFileVersionInfo_ElementName(FVI_Flag), @TempBuff, @TempBuffSize)
              TempString$ = PeekS(TempBuff, TempBuffSize)
            EndIf
            If FVI_Flag = #FVI_Language
              TempString$ = TempLang$
            EndIf
          EndIf
        EndIf
        FreeMemory(*TempBlk)
      EndIf
    EndIf
    CloseLibrary(TempLibHandle)
  EndIf
  
  ProcedureReturn(TempString$)
EndProcedure



File$  = "c:\temp\test.exe"
Debug GetFileVersionInfo_ElementName(#FVI_FileVersion) + " : " + GetFileVersionInfoString(File$, #FVI_FileVersion)
Debug GetFileVersionInfo_ElementName(#FVI_FileDescription) + " : " + GetFileVersionInfoString(File$, #FVI_FileDescription)
Debug GetFileVersionInfo_ElementName(#FVI_LegalCopyright) + " : " + GetFileVersionInfoString(File$, #FVI_LegalCopyright)
Debug GetFileVersionInfo_ElementName(#FVI_InternalName) + " : " + GetFileVersionInfoString(File$, #FVI_InternalName)
Debug GetFileVersionInfo_ElementName(#FVI_OriginalFilename) + " : " + GetFileVersionInfoString(File$, #FVI_OriginalFilename)
Debug GetFileVersionInfo_ElementName(#FVI_ProductName) + " : " + GetFileVersionInfoString(File$, #FVI_ProductName)
Debug GetFileVersionInfo_ElementName(#FVI_ProductVersion) + " : " + GetFileVersionInfoString(File$, #FVI_ProductVersion)
Debug GetFileVersionInfo_ElementName(#FVI_CompanyName) + " : " + GetFileVersionInfoString(File$, #FVI_CompanyName)
Debug GetFileVersionInfo_ElementName(#FVI_LegalTrademarks) + " : " + GetFileVersionInfoString(File$, #FVI_LegalTrademarks)
Debug GetFileVersionInfo_ElementName(#FVI_SpecialBuild) + " : " + GetFileVersionInfoString(File$, #FVI_SpecialBuild)
Debug GetFileVersionInfo_ElementName(#FVI_PrivateBuild) + " : " + GetFileVersionInfoString(File$, #FVI_PrivateBuild)
Debug GetFileVersionInfo_ElementName(#FVI_Comments) + " : " + GetFileVersionInfoString(File$, #FVI_Comments)
Debug GetFileVersionInfo_ElementName(#FVI_Language) + " : " + GetFileVersionInfoString(File$, #FVI_Language)

For x = 0 To $1100
  y$ = Trim(GetFileVersionInfoString(File$, x))
  If y$ <> ""
    Debug Hex(x) + "  " + GetFileVersionInfo_ElementName(x) + " : " + GetFileVersionInfoString(File$, x)
  EndIf
Next

Debug "end"

; IDE Options = PureBasic 4.41 (Windows - x86)
; CursorPosition = 132
; FirstLine = 103
; Folding = -
; EnableXP
; Executable = Test.exe
; IncludeVersionInfo
; VersionField0 = 1.0.0.0
; VersionField1 = 0.0.0.1
; VersionField2 = My Company
; VersionField3 = My Product
; VersionField4 = 2010
; VersionField5 = File Version
; VersionField6 = File Description
; VersionField7 = What is internal
; VersionField8 = Original Fries
; VersionField9 = © Copyright
; VersionField10 = ™ Trademark
; VersionField11 = PB 4.41
; VersionField12 = x86
; VersionField13 = nobody@nowhere.com
; VersionField14 = www.nowhere.com
; VersionField15 = VOS_NT_WINDOWS32
; VersionField16 = VFT_APP
; VersionField17 = 0800 System Default Language
; VersionField18 = Comments
; VersionField19 = Special
; VersionField21 = Additional Comments
; VersionField22 = Additional Special Field

Re: GetFileVersionInfo

Posted: Tue May 25, 2010 6:05 pm
by Rook Zimbabwe
Very nice! 8)

Re: GetFileVersionInfo

Posted: Fri Jan 26, 2018 10:41 am
by Rinzwind
Problem with specific Windows 10 applications... most info is empty. In Windows Explorer properties info is displayed correctly. Any clue?

Code: Select all

EnableExplicit

Enumeration
  #FVI_FileVersion      = $0001
  #FVI_FileDescription  = $0002
  #FVI_LegalCopyright   = $0004
  #FVI_InternalName     = $0008
  #FVI_OriginalFilename = $0010
  #FVI_ProductName      = $0020
  #FVI_ProductVersion   = $0040
  #FVI_CompanyName      = $0080
  #FVI_LegalTrademarks  = $0100
  #FVI_SpecialBuild     = $0200
  #FVI_PrivateBuild     = $0400
  #FVI_Comments         = $0800
  #FVI_Language         = $1000
  #FVI_Email            = $1001
  #FVI_Website          = $1002
  #FVI_Special          = $1003
EndEnumeration

Procedure.s GetFileVersionInfo_ElementName(ElementFlag)
  Protected TempString$ = ""
  Select ElementFlag
    Case #FVI_FileVersion
      TempString$ = "FileVersion"
    Case #FVI_FileDescription
      TempString$ = "FileDescription"
    Case #FVI_LegalCopyright
      TempString$ = "LegalCopyright"
    Case #FVI_InternalName
      TempString$ = "InternalName"
    Case #FVI_OriginalFilename
      TempString$ = "OriginalFilename"
    Case #FVI_ProductName
      TempString$ = "ProductName"
    Case #FVI_ProductVersion
      TempString$ = "ProductVersion"
    Case #FVI_CompanyName
      TempString$ = "CompanyName"
    Case #FVI_LegalTrademarks
      TempString$ = "LegalTrademarks"
    Case #FVI_SpecialBuild
      TempString$ = "SpecialBuild"
    Case #FVI_PrivateBuild
      TempString$ = "PrivateBuild"
    Case #FVI_Comments
      TempString$ = "Comments"
    Case #FVI_Language
      TempString$ = "Language"
    Case #FVI_Email
      TempString$ = "Email"
    Case #FVI_Website
      TempString$ = "Website"
    Case #FVI_Special
      TempString$ = "Special"
  EndSelect
  ProcedureReturn TempString$
EndProcedure

Procedure.s GetFileProperty(filePath.s, FVI_Flag)
  Protected TempString$ = "", TempPtr, TempBlkSize, *TempBlk
  Protected TempBuff, TempBuffSize, TempCPLI$, TempLangSize = 128, TempLang$ = Space(TempLangSize)
 
  If FileSize(filePath) >= 0
    TempBlkSize = GetFileVersionInfoSize_(filePath, @TempPtr)
    If TempBlkSize > 0
      *TempBlk = AllocateMemory(TempBlkSize)
      If *TempBlk > 0
        If GetFileVersionInfo_(filePath, 0, TempBlkSize, *TempBlk)
          If VerQueryValue_(*TempBlk, "\\VarFileInfo\\Translation", @TempBuff, @TempBuffSize)
            TempCPLI$ = RSet(Hex(PeekW(TempBuff)), 4, "0") + RSet(Hex(PeekW(TempBuff + 2)), 4, "0")
            VerLanguageName_(PeekW(TempBuff), TempLang$, TempLangSize)
          EndIf
          If VerQueryValue_(*TempBlk, "\\StringFileInfo\\" + TempCPLI$ + "\\" + GetFileVersionInfo_ElementName(FVI_Flag), @TempBuff, @TempBuffSize)
            TempString$ = PeekS(TempBuff, TempBuffSize)
          EndIf
          If FVI_Flag = #FVI_Language
            TempString$ = TempLang$
          EndIf
        EndIf
      EndIf
      FreeMemory(*TempBlk)
    EndIf
  EndIf
 
  ProcedureReturn(TempString$)
EndProcedure

Debug GetFileProperty("C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1712.3351.0_x64__8wekyb3d8bbwe\Calculator.exe", #FVI_CompanyName)

Re: GetFileVersionInfo

Posted: Fri Jan 26, 2018 1:20 pm
by blueb
Rinzwind wrote:Problem with specific Windows 10 applications... most info is empty. In Windows Explorer properties info is displayed correctly. Any clue?
Likely because of file location and permissions...

Code: Select all

Debug GetFileProperty("C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1712.3351.0_x64__8wekyb3d8bbwe\Calculator.exe", #FVI_CompanyName)
I tried your code in another folder and an actual file:

Code: Select all

Debug GetFileProperty("C:\Latest Home\7-Zip\7z.exe", #FVI_CompanyName)
Debug GetFileProperty("C:\Latest Home\7-Zip\7z.exe", #FVI_FileVersion)
Debug GetFileProperty("C:\Latest Home\7-Zip\7z.exe", #FVI_OriginalFilename)
Debug GetFileProperty("C:\Latest Home\7-Zip\7z.exe", #FVI_ProductVersion)
Results:

Code: Select all

Igor Pavlov
17.01 beta
7z.exe
17.01 beta
Used: Win10 Pro and PB 5.62 beta 1 both (x84) and (x64)

HTH

Re: GetFileVersionInfo

Posted: Fri Jan 26, 2018 2:26 pm
by Rinzwind
Get info on win32 apps works on Windows 10. On some universal apps or whatever you call them they return empty results.

Found out that setting tempcli to 040904B0 works (English). Also tried GetFileVersionInfoSizeEx with #FILE_VER_GET_NEUTRAL | #FILE_VER_GET_LOCALISED but still no result from VerQueryValue.

Anyway... seems like a problem specific to only few apps like Calculator. Another app like the Calendar C:\Program Files\WindowsApps\microsoft.windowscommunicationsapps_17.8827.21595.0_x64__8wekyb3d8bbwe\HxCalendarAppImm.exe does return info...