This script gets full version information for CompanyName/FileDescription/etc. string version info from executable. Because AHK doesn't include such a capability I took an example in VBA and recoded it in AHK
Code:
; LITTLE DEMONSTRATION: hot to fetch full string version information from
; executable files
oldErrMode:=dllCall("SetErrorMode",uint,1) ; SEM_FAILCRITICALERRORS=0x0001
verExts:="|exe|dll|drv|fon|ttf|vxd|sys|cpl|ocx|"
loop,%winDir%\*,,1
{ splitPath,A_LoopFileLongPath,,,ext
ifInString,verExts,|%ext%|
{ count ++
traytip,,%A_LoopFileLongPath%
info:=info . A_LoopFileLongPath "`t"
. FileGetFullVer(A_LoopFileLongPath,1|2|4|8|0xFFFF,"`t") "`n`n"
if (count=5)
break
}
}
dllCall("SetErrorMode",uint,oldErrMode)
if !info
{ fileSelectFile,file,1
info:=file "`t" FileGetFullVer(file,1|2|4|8|0x8000,"`t")
}
msgbox %info%
ExitApp
FileGetFullVer(file,verFlags=1,delim="") ;;
{ ifEqual,delim,,delim=|
; FLAGS: 0x0001 - numeric info
; 0x0002 - file type
; 0x0004 - file description
; 0x0008 - company name
; 0x0010 - FileVersion
; 0x0020 - Comments
; 0x0040 - InternalName
; 0x0080 - LegalCopyright
; 0x0100 - LegalTrademarks
; 0x0200 - OriginalFilename
; 0x0400 - ProductName
; 0x0800 - ProductVersion
; 0x1000 - PrivateBuild
; 0x2000 - SpecialBuild
; 0x4000 - LegalTrademarks1
; 0x8000 - clean-up empty fields
; VersionInfoStrings
; viPredefinedFirst = 0
; viLanguage = 0
; viComments = 1
; viCompanyName = 2
; viFileDescription = 3
; viFileVersion = 4
; viInternalName = 5
; viLegalCopyright = 6
; viLegalTrademarks = 7
; viOriginalFilename = 8
; viProductName = 9
; viProductVersion = 10
; viPrivateBuild = 11
; viSpecialBuild = 12
; viLegalTrademarks1 = 13 'Used by Office apps only?
; viLegalTrademarks2 = 14 'Used by Office apps only?
; viPredefinedLast = 14
;typedef struct tagVS_FIXEDFILEINFO
; 0 DWORD dwSignature;
; 4 DWORD dwStrucVersion;
; 8 DWORD dwFileVersionMS;
; 12 DWORD dwFileVersionLS;
; 16 DWORD dwProductVersionMS;
; 20 DWORD dwProductVersionLS;
; 24 DWORD dwFileFlagsMask;
; 28 DWORD dwFileFlags;
; 32 DWORD dwFileOS;
; 36 DWORD dwFileType;
; 40 DWORD dwFileSubtype;
; 44 DWORD dwFileDateMS;
; 48 DWORD dwFileDateLS;
; MAX_PATH = 260
; ; ----- VS_VERSION.dwFileFlags -----
; VS_FFI_SIGNATURE = 0xFEEF04BD
; VS_FFI_STRUCVERSION = 0x10000
; VS_FFI_FILEFLAGSMASK = 0x3F
; ; ----- VS_VERSION.dwFileFlags -----
; VS_FF_DEBUG = 0x1
; VS_FF_PRERELEASE = 0x2
; VS_FF_PATCHED = 0x4
; VS_FF_PRIVATEBUILD = 0x8
; VS_FF_INFOINFERRED = 0x10
; VS_FF_SPECIALBUILD = 0x20
; ; ----- VS_VERSION.dwFileOS -----
; VOS_UNKNOWN = 0x0
; VOS_DOS = 0x10000
; VOS_OS216 = 0x20000
; VOS_OS232 = 0x30000
; VOS_NT = 0x40000
; VOS_DOS_WINDOWS16 = 0x10001
; VOS_DOS_WINDOWS32 = 0x10004
; VOS_OS216_PM16 = 0x20002
; VOS_OS232_PM32 = 0x30003
; VOS_NT_WINDOWS32 = 0x40004
; ; ----- VS_VERSION.dwFileType -----
; VFT_UNKNOWN = 0x0
; VFT_APP = 0x1
; VFT_DLL = 0x2
; VFT_DRV = 0x3
; VFT_FONT = 0x4
; VFT_VXD = 0x5
; VFT_STATIC_LIB = 0x7
; ; **** VS_VERSION.dwFileSubtype for VFT_WINDOWS_FONT ****
; VFT2_FONT_RASTER = 0x1
; VFT2_FONT_VECTOR = 0x2
; VFT2_FONT_TRUETYPE = 0x3
; ; ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_DRV -----
; VFT2_UNKNOWN = 0x0
; VFT2_DRV_PRINTER = 0x1
; VFT2_DRV_KEYBOARD = 0x2
; VFT2_DRV_LANGUAGE = 0x3
; VFT2_DRV_DISPLAY = 0x4
; VFT2_DRV_MOUSE = 0x5
; VFT2_DRV_NETWORK = 0x6
; VFT2_DRV_SYSTEM = 0x7
; VFT2_DRV_INSTALLABLE = 0x8
; VFT2_DRV_SOUND = 0x9
; VFT2_DRV_COMM = 0xA
version=
dummy:=1
fiSize:=dllCall("version\GetFileVersionInfoSizeA",str,file,uint,&dummy)
varSetCapacity(fi,fiSize,0)
loop,1
{ if !dllCall("version\GetFileVersionInfoA",str,file, int,0, int,fiSize, uint,&fi)
break
if !dllCall("version\VerQueryValueA",uint,&fi, str,"\", uintp,fiFFI#, uintp,dummy)
break
varSetCapacity(fiFFI,13*4)
dllCall("RtlMoveMemory",uint,&fiFFI,uint,fiFFI#,uint,13*4)
version:=iif(verFlags & 1=0,""
,"v" extractInteger(fiFFI,10,0,2) "." extractInteger(fiFFI,8,0,2)
. iif(extractInteger(fiFFI,12,0,2)=0,""
,"." extractInteger(fiFFI,14,0,2) "." extractInteger(fiFFI,12,0,2)))
. iif(verFlags & 2=0,""
,"|" switch(extractInteger(fiFFI,36)+1,""
,"Application","DLL"
,"|" switch(extractInteger(fiFFI,40)+1,"","Printer ","Keyboard "
,"Language ","Display ","Mouse ","Network ","System "
,"Installable ", "Sound ","Comm. ") "driver"
,"|" switch(extractInteger(fiFFI,40),"Raster","Vector","TrueType") " font"
,"|VxD driver", "|Static Lib"))
if (verFlags & 0xFFFE)
{ if !dllCall("version\VerQueryValueA",uint,&fi, str,"\VarFileInfo\Translation", uintp,fiTrans#, uintp,dummy)
break
ifEqual,dummy,0, break
fiTrans:=0
dllCall("RtlMoveMemory",uintP,fiTrans,uint,fiTrans#,uint,4)
Lang#:=fiTrans & 0xFFFF
CP#:=fiTrans>>16
varSetCapacity(lang,256,0)
dummy:=dllCall("VerLanguageNameA",uint,Lang#, str,lang, uint,256)
stringLeft,lang,lang,%dummy%
sSubBlock:= "\StringFileInfo\" FmtHex(Lang#,4) . FmtHex(CP#,4) "\"
Company:=verGetStdValue(fi,sSubBlock "CompanyName")
if !Company
{ ; Try U.S. English...?
dummy:="\StringFileInfo\0409" FmtHex(CP#,4) "\"
Company:=verGetStdValue(fi,dummy "CompanyName")
if (Company)
sSubBlock:=dummy ; We probably found the MS version bug.
}
version:=version
. iif(verFlags & 4=0,"","|" verGetStdValue(fi,sSubBlock "FileDescription"))
. iif(verFlags & 8=0,"","|" Company)
. iif(verFlags & 0x10,"|" verGetStdValue(fi,sSubBlock "FileVersion"),"")
. iif(verFlags & 0x20,"|" verGetStdValue(fi,sSubBlock "Comments"),"")
. iif(verFlags & 0x40,"|" verGetStdValue(fi,sSubBlock "InternalName"),"")
. iif(verFlags & 0x80,"|" verGetStdValue(fi,sSubBlock "LegalCopyright"),"")
. iif(verFlags & 0x100,"|" verGetStdValue(fi,sSubBlock "LegalTrademarks"),"")
. iif(verFlags & 0x200,"|" verGetStdValue(fi,sSubBlock "OriginalFilename"),"")
. iif(verFlags & 0x400,"|" verGetStdValue(fi,sSubBlock "ProductName"),"")
. iif(verFlags & 0x800,"|" verGetStdValue(fi,sSubBlock "ProductVersion"),"")
. iif(verFlags & 0x1000,"|" verGetStdValue(fi,sSubBlock "PrivateBuild"),"")
. iif(verFlags & 0x2000,"|" verGetStdValue(fi,sSubBlock "SpecialBuild"),"")
. iif(verFlags & 0x4000,"|" verGetStdValue(fi,sSubBlock "LegalTrademarks1")
. "|" verGetStdValue(fi,sSubBlock "LegalTrademarks2"),"")
}
}
if (verFlags & 0x8000)
{ dummy=
version=|%version%|
stringReplace,version,version,|v0.0|
loop,parse,version,|
if (A_LoopField)
dummy:=dummy . delim . A_LoopField
return strMid(dummy,2)
}
if (delim<>"|")
stringReplace,version,version,|,%delim%,all
return version
}
verGetStdValue(byref fi, value) ;;
{ fiValue#:=0
dummy:=0
if !dllCall("version\VerQueryValueA",str,fi, str,value, uintp,fiValue#, uintp,dummy)
return
ifEqual,dummy,0, return
len:=dllCall("lstrlenA",uint,fiValue#)
varSetCapacity(fiValue,len+1,0)
dllCall("RtlMoveMemory",str,fiValue, uint,fiValue#, uint,len)
__trim:=A_AutoTrim
AutoTrim,on
fiValue=%fiValue%
AutoTrim,%__trim%
return fiValue
}
fmtHex(num,digits=8) ;; without "0x" padded with "0" ;;
{ varSetCapacity(s,digits+8,asc("0"))
__format:=A_FormatInteger
setformat,integer,hex
num+=0
s:=s . num
stringReplace,s,s,0x
setformat,integer,%__format%
return strRight(s,digits)
}
iif(expr, a, b) ;;
{
if (expr)
return a
else
return b
}
strLeft(s, n) ;;
{
stringLeft,s,s,%n%
return s
}
strRight(s, n) ;;
{
stringRight,s,s,%n%
return s
}
strMid(s, begin, n=0x7FFF, Left=0) ; if L<>0 then mid to the left ;;
{
if Left=0
stringMid,s,s,%begin%,%n%
else
stringMid,s,s,%begin%,%n%,L
return s
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4) ;;
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) ;;
; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}
switch(idx,val1="",val2="",val3="",val4="",val5="",val6="",val7="",val8=""
,val9="",val10="",val11="",val12="",val13="",val14="",val15="",val16="") ;;
{
return val%idx%
}