FileVersion() - FileVersionInfo simplified

Post your working scripts, libraries and tools
User avatar
SKAN
Posts: 379
Joined: 29 Sep 2013, 16:58

FileVersion() - FileVersionInfo simplified

17 Aug 2014, 17:01

Code: Select all

FileVersion( PE := "",  Qry := "040904B0\FileDescription" ) { ; by SKAN 18-Aug-2014  http://goo.gl/XdJIIC
  Local pInfo := 0
  If Sz := DllCall( "Version\GetFileVersionInfoSizeW", "WStr",PE ? PE : PE := A_AhkPath, "Int",0 )
  If DllCall( "Version\GetFileVersionInfoW", "WStr",PE, "Int",0, "UInt",VarSetCapacity( V,Sz ), "Str",V ) 
  If DllCall( "Version\VerQueryValueW", "Str",V, "WStr","\StringFileInfo\" . Qry, "PtrP",pInfo, "Int",0 )
     Return StrGet( pInfo, "UTF-16" )
}
Main intended use for FileVersion() is to identify the installed/running AutoHotkey version : MsgBox, % FileVersion() . " v" . A_AhkVersion
Parameters can be used for reading version info items from 'known PE files'.

Code: Select all

Msgbox % FileVersion( "shell32.dll"  )
Msgbox % FileVersion( "A_ScriptFullpath", "040904B0\Comments"   ) ; Compiled
Tested in AHK versions 1.1/2.0, x86/x64, Ansi/Unicode in Win versions XP, 7, 7 x64, 8.1, 8.1 x64.

:)
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: FileVersion() - FileVersionInfo simplified

18 Aug 2014, 02:22

SKAN wrote:Main intended use for FileVersion() is to identify the installed/running AutoHotkey version ...

Code: Select all

AhkBuild() {
   Return "AutoHotkey " . (A_IsUnicode ? "Unicode " : "ANSI ") . (A_PtrSize = 8 ? "64" : "32") . "-bit"
}
User avatar
SKAN
Posts: 379
Joined: 29 Sep 2013, 16:58

Re: FileVersion() - FileVersionInfo simplified

19 Aug 2014, 13:02

just me wrote:AhkBuild() {... }
Simple and efficient. Thanks :)
I wrote:Tested in AHK versions 1.1/2.0, x86/x64, Ansi/Unicode in Win versions XP, 7, 7 x64, 8.1, 8.1 x64.
All of them in single 1TB HDD of my new HTPC, confusing, and hence I needed this for my LIB.
Another usage example for FileVersion() :

Code: Select all

#Warn
DetectHiddenWindows, On

WinGet, List, List, ahk_class AutoHotkey
ALL := ""

Loop % ( List ) {
 ID := WinExist( "ahk_id " List%A_Index% )
 WinGet, PID, PID
 WinGet, PPath, ProcessPath
 ALL .= PID "`t" PPath "`n" FileVersion( PPath ) " v" FileVersion( PPath, "040904B0\FileVersion" ) "`n`n"
}

Msgbox % ALL  
I also have the following function to identify "Windows Edition" but RegRead fails with ErrorLevel 1 in v2 x86 ( did not test it in x64 )?

Code: Select all

MsgBox % WinVersion()

WinVersion() {
  VarSetCapacity( OSVEX,284,0 ), NumPut( 284,OSVEX,0,"UInt" ), DllCall( "GetVersionExW", "Ptr",&OSVEX )
  RegRead, ProductName, HKLM, SOFTWARE\Microsoft\Windows NT\CurrentVersion, ProductName
Return ProductName . ( A_Is64bitOS ? " x64" : "" ) . "`n" . StrGet( &OSVEX+20, "UTF-16" )
, ErrorLevel := NumGet( OSVEX,4,"UInt" ) "." NumGet( OSVEX,8,"UInt" ) "." NumGet( OSVEX,12,"UInt" ) 
}
Any ideas?.
Bruttosozialprodukt
Posts: 457
Joined: 24 Jan 2014, 22:28

Re: FileVersion() - FileVersionInfo simplified

30 Aug 2014, 18:49

Are

Code: Select all

FileVersion(file)
and

Code: Select all

FileGetVersionInfo_AW(process.ExecutablePath, "FileDescription")
supposed to return the same results?
Because FileVersion(file) fails on some files. (e.g. tv_w32.exe which comes with TeamViewer 9)

But maybe I'm just doing it wrong?
User avatar
SKAN
Posts: 379
Joined: 29 Sep 2013, 16:58

Re: FileVersion() - FileVersionInfo simplified

30 Aug 2014, 19:15

brutosozialprodukt wrote:Are

Code: Select all

FileVersion(file)
and

Code: Select all

FileGetVersionInfo_AW(process.ExecutablePath, "FileDescription")
supposed to return the same results?
No. FileVersion() is a simpilfied version that expects description to be in english + unicode format ( which will be the case with 99% of OS files ), whereas the full version will parse into the first available language.

In the parameter "040904B0\FileDescription", 040904B0 means

0409 = languageCode for English_United_States ( list is available in AHK Documentation under A_Language )
04B0 = Unicode
Because FileVersion(file) fails on some files. (e.g. tv_w32.exe which comes with TeamViewer 9)
Most probably the executable is not using a language code ( aka lanuage neutral ).
If that is the case, then the second parameter should be "000004B0\FileDescription"

Edit:

Code: Select all

If not Desc := FileVersion( file, "040904B0\FileDescription"   ) 
       Desc := FileVersion( file, "000004B0\FileDescription"   ) 
MsgBox % Desc
User avatar
Flipeador
Posts: 1126
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Re: FileVersion() - FileVersionInfo simplified

29 May 2015, 21:17

This works well for me:
Updated* 2016

Code: Select all

for k, v in GetFileVersionInfo(A_WinDir "\regedit.exe")
	MsgBox % k " = " v
GetFileVersionInfo(Filename) {
	;https://msdn.microsoft.com/en-us/library/windows/desktop/ms647005(v=vs.85).aspx
	if !(Size := DllCall("Version.dll\GetFileVersionInfoSizeW", "Ptr", &Filename, "Ptr", 0, "UInt")) 
		return false, ErrorLevel := 2 
	
	;https://msdn.microsoft.com/en-us/library/windows/desktop/ms647003(v=vs.85).aspx
	VarSetCapacity(VS_VERSIONINFO, Size * 2, 0)
	if !DllCall("Version.dll\GetFileVersionInfoW", "Ptr", &Filename, "UInt", 0, "UInt", Size, "Ptr", &VS_VERSIONINFO, "Int")
		return false, ErrorLevel := true

	;https://msdn.microsoft.com/en-us/library/windows/desktop/ms647464(v=vs.85).aspx
	if !DllCall("Version.dll\VerQueryValueW", "Ptr", &VS_VERSIONINFO, "Str", "\VarFileInfo\Translation", "PtrP", VERINFO, "UIntP", 0, "Int")
		return false, ErrorLevel := 3
	LangCP := "\StringFileInfo\" Format("{:04X}{:04X}", NumGet(VERINFO+0, "UShort"), NumGet(VERINFO+2, "UShort")) "\"
	
	Info := {}
	Loop, Parse, % "Comments|InternalName|ProductName|CompanyName|LegalCopyright|ProductVersion|FileDescription|LegalTrademarks|PrivateBuild|FileVersion|OriginalFilename|SpecialBuild", |
		if DllCall("Version.dll\VerQueryValueW", "Ptr", &VS_VERSIONINFO, "Str", LangCP A_LoopField, "PtrP", VERINFO, "UIntP", Size, "Int")
			Info[A_LoopField] := StrGet(VERINFO, Size)
	return Info
}

GetFileVersionInfoEx(Filename) { ;WIN_V+
	;https://msdn.microsoft.com/en-us/library/windows/desktop/aa969435(v=vs.85).aspx
	if !(Size := DllCall("Version.dll\GetFileVersionInfoSizeExW", "UInt", 0x01, "Ptr", &Filename, "Ptr", 0, "UInt")) 
		return false, ErrorLevel := 2 
	
	;https://msdn.microsoft.com/en-us/library/windows/desktop/aa969434(v=vs.85).aspx
	VarSetCapacity(VS_VERSIONINFO, Size * 2, 0)
	if !DllCall("Version.dll\GetFileVersionInfoExW", "UInt", 0x01, "Ptr", &Filename, "UInt", 0, "UInt", Size, "Ptr", &VS_VERSIONINFO, "Int")
		return false, ErrorLevel := true
	
	;https://msdn.microsoft.com/en-us/library/windows/desktop/ms647464(v=vs.85).aspx
	if !DllCall("Version.dll\VerQueryValueW", "Ptr", &VS_VERSIONINFO, "Str", "\VarFileInfo\Translation", "PtrP", VERINFO, "UIntP", 0, "Int")
		return false, ErrorLevel := 3
	LangCP := "\StringFileInfo\" Format("{:04X}{:04X}", NumGet(VERINFO+0, "UShort"), NumGet(VERINFO+2, "UShort")) "\"
	
	Info := {}
	Loop, Parse, % "Comments|InternalName|ProductName|CompanyName|LegalCopyright|ProductVersion|FileDescription|LegalTrademarks|PrivateBuild|FileVersion|OriginalFilename|SpecialBuild", |
		if DllCall("Version.dll\VerQueryValueW", "Ptr", &VS_VERSIONINFO, "Str", LangCP A_LoopField, "PtrP", VERINFO, "UIntP", Size, "Int")
			Info[A_LoopField] := StrGet(VERINFO, Size)
	return Info
}
Last edited by Flipeador on 18 Jan 2016, 22:45, edited 2 times in total.
lexikos
Posts: 6501
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: FileVersion() - FileVersionInfo simplified

29 May 2015, 23:18

This version is shorter and also works with ANSI builds:

Code: Select all

MsgBox % FileGetInfo( comspec ).CompanyName
MsgBox % FileGetInfo( A_WinDir "\system32\calc.exe" ).FileDescription

FileGetInfo( lptstrFilename) {
	List := "Comments InternalName ProductName CompanyName LegalCopyright ProductVersion"
		. " FileDescription LegalTrademarks PrivateBuild FileVersion OriginalFilename SpecialBuild"
	dwLen := DllCall("Version.dll\GetFileVersionInfoSize", "Str", lptstrFilename, "Ptr", 0)
	dwLen := VarSetCapacity( lpData, dwLen + A_PtrSize)
	DllCall("Version.dll\GetFileVersionInfo", "Str", lptstrFilename, "UInt", 0, "UInt", dwLen, "Ptr", &lpData) 
	DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\VarFileInfo\Translation", "PtrP", lplpBuffer, "PtrP", puLen )
	sLangCP := Format("{:04X}{:04X}", NumGet(lplpBuffer+0, "UShort"), NumGet(lplpBuffer+2, "UShort"))
	i := {}
	Loop, Parse, % List, %A_Space%
		DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\StringFileInfo\" sLangCp "\" A_LoopField, "PtrP", lplpBuffer, "PtrP", puLen )
		? i[A_LoopField] := StrGet(lplpBuffer, puLen) : ""
	return i
}
User avatar
Maestr0
Posts: 78
Joined: 05 Dec 2013, 17:43

Re: FileVersion() - FileVersionInfo simplified

19 Aug 2019, 04:48

lexikos wrote:
29 May 2015, 23:18
This version is shorter and also works with ANSI builds:

Code: Select all

MsgBox % FileGetInfo( comspec ).CompanyName
MsgBox % FileGetInfo( A_WinDir "\system32\calc.exe" ).FileDescription

FileGetInfo( lptstrFilename) {
	List := "Comments InternalName ProductName CompanyName LegalCopyright ProductVersion"
		. " FileDescription LegalTrademarks PrivateBuild FileVersion OriginalFilename SpecialBuild"
	dwLen := DllCall("Version.dll\GetFileVersionInfoSize", "Str", lptstrFilename, "Ptr", 0)
	dwLen := VarSetCapacity( lpData, dwLen + A_PtrSize)
	DllCall("Version.dll\GetFileVersionInfo", "Str", lptstrFilename, "UInt", 0, "UInt", dwLen, "Ptr", &lpData) 
	DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\VarFileInfo\Translation", "PtrP", lplpBuffer, "PtrP", puLen )
	sLangCP := Format("{:04X}{:04X}", NumGet(lplpBuffer+0, "UShort"), NumGet(lplpBuffer+2, "UShort"))
	i := {}
	Loop, Parse, % List, %A_Space%
		DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\StringFileInfo\" sLangCp "\" A_LoopField, "PtrP", lplpBuffer, "PtrP", puLen )
		? i[A_LoopField] := StrGet(lplpBuffer, puLen) : ""
	return i
}
for ahk v2 a104, this works:

Code: Select all

MsgBox FileGetInfo( A_WinDir "\system32\calc.exe" )["FileDescription"]

FileGetInfo( lptstrFilename) {
	List := "Comments InternalName ProductName CompanyName LegalCopyright ProductVersion"
		. " FileDescription LegalTrademarks PrivateBuild FileVersion OriginalFilename SpecialBuild"
	dwLen := DllCall("Version.dll\GetFileVersionInfoSize", "Str", lptstrFilename, "Ptr", 0)
	dwLen := VarSetCapacity( lpData, dwLen + A_PtrSize)
	DllCall("Version.dll\GetFileVersionInfo", "Str", lptstrFilename, "UInt", 0, "UInt", dwLen, "Ptr", &lpData) 
	DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\VarFileInfo\Translation", "PtrP", lplpBuffer, "PtrP", puLen )
	sLangCP := Format("{:04X}{:04X}", NumGet(lplpBuffer+0, "UShort"), NumGet(lplpBuffer+2, "UShort"))
	i := Map()
	Loop Parse, List, A_Space
	{
		DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\StringFileInfo\" sLangCp "\" A_LoopField, "PtrP", lplpBuffer, "PtrP", puLen )
		? i[A_LoopField] := StrGet(lplpBuffer, puLen) : ""
	}
	return i
}

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Kellyzkorner_NJ and 39 guests