; 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% }
[::script::GetFullVersionInfo] string version info for execs
Started by
wOxxOm
, Mar 12 2006 05:06 PM
28 replies to this topic
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
#1
-
Posted 12 March 2006 - 05:06 PM
Thanks a lot, I was looking for this a long time. Do you also know how to SET/MODIDFY the comment?
#3
-
Posted 13 March 2006 - 07:43 AM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
The code works on executables in the windir.
But I tried your function on Word documents to fetch the comments stored in the file info. Unfortunately the dllcall in
Edit: the fiSize is zero from
But I tried your function on Word documents to fetch the comments stored in the file info. Unfortunately the dllcall in
if !dllCall("version\GetFileVersionInfoA",str,file, int,0, int,fiSize, uint,&fi) breakdoesn't work and the loop breaks. Is there a solution to fetch the comments from a word document?
Edit: the fiSize is zero from
fiSize:=dllCall("version\GetFileVersionInfoSizeA",str,file,uint,&dummy)So I guess the file info of word documents can't be accessed with the version.dll functions.
#4
-
Posted 13 March 2006 - 09:57 AM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf:
- AFAIK, this information is read-only, unless you use the same method as Resource Hacker. I don't know this method, perhaps it just does binary parsing and rewriting. Note that some virus checkers may not like this operation...
- GetFileVersionInfo just reads the resource of the executable. The Summary (is that the English name?) tab of the properties of a Word (Office) document is a very different beast. I believe it is serialized Ole information, but I don't know much more. I think that the Summary tab of other documents (simple text document, for example), is stored elsewhere (perhaps in the registry) by the OS. An image have differents information, like the size, resolution and color depth.
- AFAIK, this information is read-only, unless you use the same method as Resource Hacker. I don't know this method, perhaps it just does binary parsing and rewriting. Note that some virus checkers may not like this operation...
- GetFileVersionInfo just reads the resource of the executable. The Summary (is that the English name?) tab of the properties of a Word (Office) document is a very different beast. I believe it is serialized Ole information, but I don't know much more. I think that the Summary tab of other documents (simple text document, for example), is stored elsewhere (perhaps in the registry) by the OS. An image have differents information, like the size, resolution and color depth.
#5
-
Posted 13 March 2006 - 10:08 AM
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
The information presented in the "Summary" tab of a file's properties is stored in an alternate stream on NTFS formatted partitions.
Check the free tool, Streams, from Sysinternals.
Check the free tool, Streams, from Sysinternals.
#6
-
Posted 13 March 2006 - 04:18 PM
I knew about alternate streams, but I did check again. I used the tool you gave the link too, but the app tells me that the information is not being found (no streams are found). But the files have text in ther comment field.
It seams to be in the stream. But the funny thing is that it is not only limited to NTFS. If you send these files by email or put them to a server and load them back, the data is still there. I guess that wouldn't happen with an normal alternate stream.
It seams to be in the stream. But the funny thing is that it is not only limited to NTFS. If you send these files by email or put them to a server and load them back, the data is still there. I guess that wouldn't happen with an normal alternate stream.
#7
-
Posted 13 March 2006 - 05:48 PM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
Very interesting information, I didn't knew about these alternate streams.
Note: the streams tool actually want file pattern, not directory. "streams ." or "streams C:\tmp" doesn't work, you have to use -s or to add \* to get it working.
Play with streams:
> echo Foo Bar Gah > ARealFile.txt:aStreamName
> more < ARealFile.txt:aStreamName
Foo Bar Gah
You can use different stream names for the same file...
I will play and see if these streams can be accessed from AHK. Probably should work with Run %comspec% /c.
The streams written from the Summary tab for the file Properties have strange names: ♣DocumentSummaryInformation and ♣SummaryInformation (displayed as a cross under cmd, as a clover in my browser) and seems harder to access (probably binary data).
Mmm, I see that shimanov actually provided similar information in the topic he gave a link to.
Note: the streams tool actually want file pattern, not directory. "streams ." or "streams C:\tmp" doesn't work, you have to use -s or to add \* to get it working.
Play with streams:
> echo Foo Bar Gah > ARealFile.txt:aStreamName
> more < ARealFile.txt:aStreamName
Foo Bar Gah
You can use different stream names for the same file...
I will play and see if these streams can be accessed from AHK. Probably should work with Run %comspec% /c
The streams written from the Summary tab for the file Properties have strange names: ♣DocumentSummaryInformation and ♣SummaryInformation (displayed as a cross under cmd, as a clover in my browser) and seems harder to access (probably binary data).
Mmm, I see that shimanov actually provided similar information in the topic he gave a link to.
#8
-
Posted 13 March 2006 - 05:50 PM
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Hi PhiLho,
I couldn't get the streams visble with streams.exe. How did you do it?
I tried absolut and relative path. I tried \*, *.doc, *.* but I never got the ♣DocumentSummaryInformation shown.
I couldn't get the streams visble with streams.exe. How did you do it?
I tried absolut and relative path. I tried \*, *.doc, *.* but I never got the ♣DocumentSummaryInformation shown.
#9
-
Posted 13 March 2006 - 06:02 PM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
I created a little text file (in WinXP SP2).
Show properties (Alt+Enter in Explorer), go to Summary tab (or whatever it is really called in your locale... "Résumé" en français...)
In Simple mode (not Advanced), you can enter some data. Validate.
Show properties (Alt+Enter in Explorer), go to Summary tab (or whatever it is really called in your locale... "Résumé" en français...)
In Simple mode (not Advanced), you can enter some data. Validate.
> streams .\* Streams v1.53 - Enumerate alternate NTFS data streams Copyright (C) 1999-2005 Mark Russinovich Sysinternals - www.sysinternals.com E:\tmp\FooBar.txt: :♣DocumentSummaryInformation:$DATA 116 :♣SummaryInformation:$DATA 256 :anotherStream:$DATA 14 :stream:$DATA 20 :{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA 0The steam and anotherStream were created using the redirection method I explain above.
#10
-
Posted 14 March 2006 - 11:15 AM
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
I could reproduce it with a text file. But for word files it doesn't show anything.
#11
-
Posted 14 March 2006 - 11:23 AM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
To quote myself:
OK, searching a bit on CodeProject, I found an article which can be of interest for you...
You can have Office summary information even on non-NTFS systems... In this case, the additional tab is a shell extension.The Summary (is that the English name?) tab of the properties of a Word (Office) document is a very different beast. I believe it is serialized Ole information, but I don't know much more.
OK, searching a bit on CodeProject, I found an article which can be of interest for you...
#12
-
Posted 14 March 2006 - 11:48 AM
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Thank you for the link to the CodeProject. It seams close to what I want. (Is it also a command line tool?) The screenshot suggests that the text in the streams is shown as binary. I wonder how he is editing the streams? In Hex-Mode via a GUI?
I can't compile the source code, and I do not understand the code that he posted in his post, So I do not know how to find out if this could be of any use. I come to the conclusion that I badly need help, since this is to much over my head and knowledge.
I can't compile the source code, and I do not understand the code that he posted in his post, So I do not know how to find out if this could be of any use. I come to the conclusion that I badly need help, since this is to much over my head and knowledge.
#13
-
Posted 14 March 2006 - 12:53 PM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
Another CodeProject article. The demo isn't compiled, alas.
Found yet another article explaining a bit the mystery of the streams shown by the Sysinternals tool.
Note: to read the remainder of the article, you can enter the login name/password pair: busy/boss
Found the trick somewhere on the Net (in a forum or discussion list). It seems the access was generated/given with BugMeNot...
An old Byte article explains some of the concepts being Ole.
PS.: most of these links are found searching OLE Document / Structured Document on Google.
(I write this as I investigate...)
Aha! I found an interesting article by Microsoft itself! They give a DLL (by actually an ActiveX) to access Office document properties. Alas, you need Com to use it. Perhaps one can write VBScript or JScript code to use it.
Aha again! Found a command line tool to access these properties! We are getting close.
I have not much time to test it right now, but I am sure you will be eager to test it yourself...
That's all for now. :-)
Found yet another article explaining a bit the mystery of the streams shown by the Sysinternals tool.
Note: to read the remainder of the article, you can enter the login name/password pair: busy/boss
Found the trick somewhere on the Net (in a forum or discussion list). It seems the access was generated/given with BugMeNot...
An old Byte article explains some of the concepts being Ole.
PS.: most of these links are found searching OLE Document / Structured Document on Google.
(I write this as I investigate...)
Aha! I found an interesting article by Microsoft itself! They give a DLL (by actually an ActiveX) to access Office document properties. Alas, you need Com to use it. Perhaps one can write VBScript or JScript code to use it.
Aha again! Found a command line tool to access these properties! We are getting close.
I have not much time to test it right now, but I am sure you will be eager to test it yourself...
That's all for now. :-)
#14
-
Posted 14 March 2006 - 01:39 PM
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Thanks a lot.
I had an older version of outwit (1.23) on my disc, but didn't know it had these capabilities. I downloaded the new version (1.26) and tested it. It works. I can read the comments of the document. *happy*
Now, of cause, I "need" (want) a way to edit/add comments to a word file. I will take a look at the articles.
Thanks a again for your help, very much appreciated.
I had an older version of outwit (1.23) on my disc, but didn't know it had these capabilities. I downloaded the new version (1.26) and tested it. It works. I can read the comments of the document. *happy*
Now, of cause, I "need" (want) a way to edit/add comments to a word file. I will take a look at the articles.
Thanks a again for your help, very much appreciated.
#15
-
Posted 14 March 2006 - 02:14 PM
Ciao
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.
toralf
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.