Jump to content

VBScript to retrieve the Version info from an EXE


Recommended Posts

Hello,

I have been searching for a while to find something that would give me the version information from microsoft patches, because I got burned too many times with Micro$ofts stupid way they release their patches. Some use Update.exe and some use msiexec.exe and since they use different switches for the silent install I have to know ahead of time and hard code the stupid switches during the install. This script would allow me to check the Installer Engine and automatically use the correct switches. :wacko:

I have tested the attached vbscript and modified it slightly to give me the Installer Engine from the Version tab in the file properties, but I can't figure out how to convert it to AutoIT.

Could anybody give me a hand with this.

PS. it uses Binary reads of the executable's header information to retrieve the data. :D

File Props.txt is the VBscript.

File Props.au3 is my feeble attempt at a conversion.

edit: removed my feeble attempt since there is now a working AutoIT conversion.

Thanks,

Mike

Edited by MikeOsdx
Link to comment
Share on other sites

Hello,

I have been searching for a while to find something that would give me the version information from microsoft patches, because I got burned too many times with Micro$ofts stupid way they release their patches. Some use Update.exe and some use msiexec.exe and since they use different switches for the silent install I have to know ahead of time and hard code the stupid switches during the install. This script would allow me to check the Installer Engine and automatically use the correct switches. :wacko:

I have tested the attached vbscript and modified it slightly to give me the Installer Engine from the Version tab in the file properties, but I can't figure out how to convert it to AutoIT.

Could anybody give me a hand with this.

PS. it uses Binary reads of the executable's header information to retrieve the data. :D

File Props.txt is the VBscript.

File Props.au3 is my feeble attempt at a conversion.

Thanks,

Mike

Mike

Have you tried Simucals UDF

in scripts n scraps

Link

worth a go

HardCopy

Contributions: UDF _DateYearFirstChildren are like Farts, you can just about stand your own.Why am I not a Vegetarian?...Well...my ancestors didn't fight & evolve to the Top of the food chain for me to survive on Salad

Link to comment
Share on other sites

Mike

Have you tried Simucals UDF

in scripts n scraps

Link

worth a go

HardCopy

I tried that first, but it only gives information from the General Tab. and I need info from the Version Tab. Unless I'm not seeing something? I upped the variable in his script to 70 outputs and it does not display the Installer Engine anywhere.

Mike

Edited by MikeOsdx
Link to comment
Share on other sites

I tried that first, but it only gives information from the General Tab. and I need info from the Version Tab. Unless I'm not seeing something? I upped the variable in his script to 70 outputs and it does not display the Installer Engine anywhere.

Mike

Ok mike , Taken a look myself

Simucal parameters only go up to 34

the info u seek is in 36 37 38 39

so just use one of those numbers as the parameter and it should work.

HardCopy

EDIT *** ack...just reread your reply..... u tried that

I tested on the Autoit EXE and came back with version info

Edited by HardCopy

Contributions: UDF _DateYearFirstChildren are like Farts, you can just about stand your own.Why am I not a Vegetarian?...Well...my ancestors didn't fight & evolve to the Top of the food chain for me to survive on Salad

Link to comment
Share on other sites

I guess I edited my last post a little too late for you to read. I upped the variables in Simucals script to 70 and it does not display the Installer engine anywhere.

35 - 39 displays information but not what I need.

Mike

Then thats me exhausted of ideas then.

Hope you get the result you need from another forumner.

Regards

HardCopy

Contributions: UDF _DateYearFirstChildren are like Farts, you can just about stand your own.Why am I not a Vegetarian?...Well...my ancestors didn't fight & evolve to the Top of the food chain for me to survive on Salad

Link to comment
Share on other sites

CMenu by mHz.

CyberSlug did some work with Peid for Universal Silent Switch Finder.

USSF

Edited by eltorro
Link to comment
Share on other sites

CMenu by mHz.

CyberSlug did some work with Peid for Universal Silent Switch Finder.

USSF

Thanks, but I need to integrate this with my own code and that's already compiled.

I will take a look at the PEiD thing that is mentioned in the CMenu details.

The part I'm stuck at on the vbscript is line 152, the binary read where it skips 12 then reads 2, acording to AutoIT help file i can only read 512 at a time. Anybody have any ideas?

Thanks,

Mike

Link to comment
Share on other sites

I am not sure where your at in the script but this might work.

;======= I am now lost ========================
;~ $Boo = False
;~ $TS = FileOpen($sFilePath, 4)
;~ TS.Skip LocRes + 12  ;-- get number of names from bytes 13,14 in top level "Type" directory.
    ;We want to skip $LocRes+12 bytes, read 2 more , read 2 more.
    ;so read 16 and dump/ignore first 12
    $s1a=FileRead($TS,$LocRes +16)
    FileClose($TS)
;~ s1 = TS.Read(2)       ;-- Read bytes 13,14 to get number of named resource types.
    $s1=StringMid($s1a,13,2)
    ;not sure on the next 2 lines
    $aS1 = _GetArray($s1) ; get array from string
;~ iNum1 = Asc(s1)       ;-- number of names.
    $iNum1 = _GetNumFromBytes($aS1)
;~ s1 = TS.Read(2)       ;-- Read bytes 15,16 to get number of numbered resource types.
    $s2= StringMid($s1a,15,2)
;~ iNum2 = Asc(s1)       ;-- number of nums.
    $aS2 =_GetArray($s2)
    $iNum2 = _GetNumFromBytes($aS2)
;~ If (iNum2 = 0) Then '-- no numbered entries. have to quit here.
    if $iNum2= 0 Then
        Return 3
;~ TS.Close
;~ Set TS = Nothing
;~ GetVersionInfo = 3  'failed to find version info in resource table.
;~ Exit Function
;~ End If
    EndIf
oÝ÷ Ø    l£*.(!·§¶Ú©àzØ^~éÜuç%j·­¢ë$^}ú+Ó~Eëvjëh×6Func _GetVersionInfo($sFilePath, ByRef $ARet2)

I hope this helps.

Link to comment
Share on other sites

OK,

I have given up on trying to convert the file to AU3.

I was able to figure out enought to modify the vbscript to output only the info I need to a file. I am now launching the .vbs from an autoit script, waiting for it to finish and then reading the info from the temp file.

I have attached both the updated File Props.vbs as a txt file. and the PatchProp.au3 file.

Now I just have to integrate the PatchProp.au3 into my main script and I'm all set.

Thanks to those who tried to help.

Mike

File_Props.txt

PatchProp.au3

Link to comment
Share on other sites

OK,

I have given up on trying to convert the file to AU3.

I was able to figure out enought to modify the vbscript to output only the info I need to a file. I am now launching the .vbs from an autoit script, waiting for it to finish and then reading the info from the temp file.

I have attached both the updated File Props.vbs as a txt file. and the PatchProp.au3 file.

Now I just have to integrate the PatchProp.au3 into my main script and I'm all set.

Thanks to those who tried to help.

Mike

You can try this conversion.

Edit 2 : Now working. fixed problem with offset calculation.

Edit 3 : Updated code is in later post.

Edited by eltorro
Link to comment
Share on other sites

this should get you closer

;-- This script includes a class and a demo. Drop any PE file onto the script (EXE, DLL, OCX)
;-- to get file properties. The class, ClsProps, is a complete set of all functions needed
;-- get file properties using only VBS and the Textstream object.
;-- The file properties returned are those that are found when a file is right-clicked,
;-- Properties menu is clicked, and Version tab is selected. This information
;-- is included in most PE (portable executable) files.
;-- Thank you to Ed Gruberman (http://www.rjump.com) for help with this code.
;-- He corrected a bug and also worked out the "aspack" variation whereby some
;-- PE files have been compressed and require a different method to find the version info.  j.
;-- NOTE: This script is written to be compact for pasting into scripts. It uses simplified versions of some functions from
;-- the Textstream Binary Ops and Base 64 download, using only the functionality needed to get file version info.,
;--  in order to keep this class as small as possible. If you want to use functions such as _GetArray or _GetByteString
;-- you may want to download the other package. It provides a fairly complete set of methods for working with binary files.
;-- Demo script --------------------
;~ Dim $Arg, cPE, $i2, $AReturn
;~      If WScript.arguments.count = 0 Then
;~         MsgBox( 266288 , @ScriptName, "Drop A PE file [EXE-DLL-OCX] onto this script to get version information.")
;~          WScript.quit
;~      Else
;~          $Arg = WScript.arguments.item(0)
;~      EndIf
Local $Arg, $i2, $AReturn
$Arg = "WXP-KB914388-DHCP.exe"
Global $FSO, $TS, $sAst, $ANums, $Char1
$sAst = "*"
$Char1 = Chr(1)
$FSO = ObjCreate("Scripting.FileSystemObject")
$i2 = _GetVersionInfo($Arg, $AReturn)
Switch $i2
    Case 1
        MsgBox(266288, @ScriptName, "File path not valid")
    Case 2
        MsgBox(266288, @ScriptName, "Unable to find Resource table header in file.")
    Case 3
        MsgBox(266288, @ScriptName, "Unable to find file version info. in file.")
    Case 4
        MsgBox(266288, @ScriptName, "This is not a PE file.")
    Case 5
        MsgBox(266288, @ScriptName, "This is a 16-bit executable. It is not a PE file.")
    Case 0  ; success
        $s = "Company: " & $AReturn (0) & @CRLF
        $s = $s & "File Description: " & $AReturn (1) & @CRLF
        $s = $s & "File Version: " & $AReturn (2) & @CRLF
        $s = $s & "Product Name: " & $AReturn (3) & @CRLF
        $s = $s & "Copyright: " & $AReturn (4) & @CRLF
        $s = $s & "Original file name: " & $AReturn (5) & @CRLF
        $s = $s & "Installer Engine:  " & $AReturn (6) & @CRLF
        MsgBox(266288, @ScriptName, $Arg & @CRLF & @CRLF & $s)
EndSwitch
;-- End demo script ------------------------------------------------------------
;-- //////////////////////// Start Class:   ClsProps   ///////////////////////////////////////////////
;  Functions in this class. (All functions are needed for getting file version information.)
;   Public Function _GetVersionInfo($sFilePath, $ARet2)  - returns version information For PE files.
;                                                                On success $ARet2 returns array(5) containing version info. strings for file.
;    Function return error codes:    0 = success.      1 = invalid file path.      2 = no .rsrc table listed in section table.
;    3 = failed to find version info.       4 = not a PE file.       5 = file is a 16-bit executable. ("NE" file rather than "PE")
;     Private (internal) functions:
;        _GetArray(StringIn) - convert a string to an array of byte values.
;        _GetByteString(StringIn, $SnipUnicode) - convert a string to a manageable version. If $SnipUnicode = True then get only every 2nd byte.
;        _GetNumFromBytes(array) - takes array of ubound 1 or 3. return numeric value for 2 or 4 bytes.
;----------------////////////  --- BEGIN Class HERE ---  /////////////////////-------------------------------------------
;-- The public function in this class: _GetVersionInfo -----------------------------------------
Func _GetVersionInfo($sFilePath, ByRef $ARet2)  ;-- return array(5)
    Local $ARet, $s1, $sB, $Pt1, $sRes, $A1, $A4[3], $A2[1], $LocRes, $VLocRes, $SizeRes, $iOff, $Boo, $sVerString, $sMarker
    Local $iNum1, $iNum2, $iReadPt, $iNum3, $LocAspack, $VLocAspack, $VIOffset, $ReadOffset, $BooAspack
    ;   On Error Resume Next
    If ($FSO.FileExists ($sFilePath) = False) Then
        Return 1  ;bad path.
    EndIf
    $sRes = ".rsrc"
    $sVerString = "VS_VER"
    $BooAspack = False
    $TS = $FSO.OpenTextFile ($sFilePath, 1)
;~  $s1 = String($TS.Read (2048)) ;-- Read first 2 KB.
    For $x = 1 To 2048
        $s1 = $s1 & String($TS.Read(1)) ;-- Read first 2 KB.
    Next
    $TS.Close
    ConsoleWrite($s1 & @LF)
    $TS = 0
    ConsoleWrite(StringMid($s1, 61, 2) & @LF)
    $A1 = _GetArray(StringMid($s1, 61, 2))  ;-- get number value at offset 60 that points to PE signature address.
    $iNum1 = (_GetNumFromBytes($A1) + 1)     ;-- get offset of "PE00"
    $sB = _GetByteString($s1, False)  ;-- get a workable string with Chr(0) replaced by "*".
    $sMarker = StringMid($sB, $iNum1, 4)
    If ($sMarker <> "PE**") Then
        If StringLeft($sMarker, 2) = "NE" Then
            Return 5  ;-- 16 bit.
        Else
            Return 4  ;-- no PE signature found.
        EndIf
    EndIf
    $Pt1 = StringInStr($sB, $sRes)   ;-- find .rsrc table.
    If ($Pt1 = 0) Then
        Return 2  ;no resource table header found.
    EndIf
    $Pt1 = $Pt1 + 12  ;--  size of raw data is 4 bytes at offset of 16 into the .rsrc table.
    $A1 = _GetArray(StringMid($s1, $Pt1, 12))  ;-- get the same string as a numeric array to Read offset numbers.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff]
    Next
    $VLocRes = _GetNumFromBytes($A4)
    For $iOff = 0 To 3
        $A4[$iOff] = $A1 ($iOff + 4)
    Next
    $SizeRes = _GetNumFromBytes($A4) ;--size of resource section in bytes.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 8]
    Next
    $LocRes = _GetNumFromBytes($A4)    ;-- offset location of resource section.
    $Pt1 = StringInStr(1, $sB, ".aspack")   ;-- find .rsrc table.
    If ($Pt1 > 0) Then
        $BooAspack = True
        $Pt1 = $Pt1 + 12    ;--  virtual offset is first 4 bytes; raw offset is bytes 9-12.
        $A1 = _GetArray(StringMid($s1, $Pt1, 12))
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff]
        Next
        $VLocAspack = _GetNumFromBytes($A4)
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff + 8]
        Next
        $LocAspack = _GetNumFromBytes($A4)
    EndIf
    $Boo = False
    $TS = $FSO.OpenTextFile ($sFilePath, 1)
    $TS.Skip ($LocRes + 12)  ;-- get number of names from bytes 13,14 in top level "Type" directory.
    $s1 = $TS.Read (2)       ;-- Read bytes 13,14 to get number of named resource types.
    $iNum1 = Asc($s1)       ;-- number of names.
    $s1 = $TS.Read (2)       ;-- Read bytes 15,16 to get number of numbered resource types.
    $iNum2 = Asc($s1)       ;-- number of nums.
    If ($iNum2 = 0) Then ;-- no numbered entries. have to quit here.
        $TS.Close
        $TS = 0
        Return 3  ;failed to find version info in resource table.
    EndIf
    If ($iNum1 > 0) Then $TS.Skip ($iNum1 * 8) ;-- Skip past named entries.
    $iReadPt = $LocRes + 16 + ($iNum1 * 8)  ;-- update file offset variable because this will be needed.
    $Boo = False
    For $iOff = 1 To $iNum2
        $s1 = $TS.Read (8)
        $iReadPt = $iReadPt + 8
        If (Asc($s1) = 16) Then  ;-- this is version info. entry.
            $Boo = True
            ExitLoop
        EndIf
    Next
    If ($Boo = False) Then  ;-- have to quit. no version info. entry found.
        $TS.Close
        $TS = 0
        Return 3  ;failed to find version info in resource table.
    EndIf
    $A1 = _GetArray($s1)  ;-- get a byte array for version info entry at top level.
    $iOff = 0
    $iNum3 = 1
    ;Do
    While 1
        For $iNum1 = 0 To 2  ;-- get offset number to next level from 2nd 4 bytes of entry structure.
            $A4[$iNum1] = $A1[$iNum1 + 4]
        Next
        $A4[3] = 0
        $iNum2 = _GetNumFromBytes($A4)
        If ($A1[7] > 127) Then  ;-- high bit was set in entry offset value, so it;s just a pointer to another pointer.
            $iNum2 = $LocRes + $iNum2 + 16
            $TS.Skip ($iNum2 - $iReadPt)   ;- 1)
            $s1 = $TS.Read (8)
            $iReadPt = $iReadPt + (($iNum2 - $iReadPt) + 8)
            $A1 = _GetArray($s1)
        Else  ;-- this is the offset of version info offset info.!
            $iOff = ($iNum2 + $LocRes)
            ;ExitLoop
            ExitLoop
        EndIf
        $iNum3 = $iNum3 + 1
        If ($iNum3 > 10) Then ExitLoop
    WEnd
    ;Loop
    If ($iOff = 0) Then  ;-- have to quit. no final offset found.
        $TS.Close
        $TS = 0
        Return 3  ;failed to find version info in resource table.
    EndIf
    $TS.Skip ($iOff - $iReadPt)
    $s1 = $TS.Read (8)
    $iReadPt = $iReadPt + (($iOff - $iReadPt) + 8)
    $A1 = _GetArray($s1)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1]
    Next
    $VIOffset = _GetNumFromBytes($A4)  ;--offset of version info. given in .rsrc section.
    $ReadOffset = (($VIOffset - $VLocRes) + $LocRes)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1 + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4)
    $TS.Skip ($ReadOffset - $iReadPt)
    $s1 = $TS.Read ($SizeRes)  ;-- read out the entire FileVersionInfo data area.
    $TS.Close
    $TS = 0
    $sB = _GetByteString($s1, True) ;-- snip unicode.
    $Pt1 = StringInStr(1, $sB, $sVerString)
    If ($Pt1 > 0) Then        ;-- "VS_VER" was found, so process the string and quit.
        $ARet = _ProcessRes($sB)
        $ARet2 = $ARet
        Return 0  ; ok
    ElseIf ($BooAspack = True) Then   ;-- if "VS_VER" was not found but there is an "aspack" section then try that.
        $ReadOffset = (($VIOffset - $VLocAspack) + $LocAspack)  ;-- calculate a new file version info data offset.
        $TS = $FSO.OpenTextFile ($sFilePath, 1)  ;-- The file was closed and is now re-opened here. Keeping the file
        $TS.Skip ($ReadOffset)                            ;-- open "just in case" wouldn;t have helped because the file pointer
        $s1 = $TS.Read ($SizeRes)                     ;-- for this read may be further back thean the pointer was when the file
        $TS.Close                                  ;-- was closed. So rather than try to sort out the read point, the file is just
        $TS = 0                        ;-- opened fresh and Skip is used.
        $sB = _GetByteString($s1, True)
        $Pt1 = StringInStr($sB, $sVerString)
        If ($Pt1 > 0) Then
            $ARet = _ProcessRes($sB)
            $ARet2 = $ARet
            Return 0  ; ok
        Else
            Return 3  ;failed to find version info in resource table.
        EndIf
    Else
        Return 3  ;failed to find version info in resource table.
    EndIf
EndFunc   ;==>_GetVersionInfo
Func _ProcessRes($sDat)
    Dim $AInfo[6]
    ;      On Error Resume Next
    $AInfo[0] = _GetInfo($sDat, "CompanyName")
    $AInfo[1] = _GetInfo($sDat, "FileDescription")
    $AInfo[2] = _GetInfo($sDat, "FileVersion")
    $AInfo[3] = _GetInfo($sDat, "ProductName")
    $AInfo[4] = _GetInfo($sDat, "LegalCopyright")
    $AInfo[5] = _GetInfo($sDat, "OriginalFilename")
    $AInfo[6] = _GetInfo($sDat, "Installer Engine")
    Return $AInfo
EndFunc   ;==> _ProcessRes
Func _GetInfo($sStr, $sVal)
    Dim $Pta, $Ptb, $LenVal, $s4
    ;       On Error Resume Next
    ;    _GetInfo = ""
    $LenVal = StringLen($sVal) + 1  ;-- length of info string: "CompanyName" = 11
    $Pta = StringInStr($sStr, $sVal)  ;-- find string name.
    If ($Pta > 0) Then
        $Pta = $Pta + $LenVal
        ;$Ptb = InStr(($Pta + 1), $sStr, $sAst)   ;-- look for next *. some properties are Name**value** and some are
        $Ptb = StringInStr(StringTrimLeft($sStr, ($Pta + 1)), $sAst)   ;-- look for next *. some properties are Name**value** and some are
        If $Ptb > ($Pta + 2) Then              ;-- Name*value**. So start looking at 3rd character after. If that
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))    ;-- character is * then it;s Name*** which means there;s
            $s4 = StringReplace($s4, $sAst, "")                                           ;--no value for that specific property.
            If StringInStr($s4, $Char1, 0) = 0 Then Return $s4   ;-- check for Chr(1) which seems to be found
        EndIf                             ; between values. If it;s in the string that means there is no value for
        ; this property and function has actually read next property name.
    EndIf
EndFunc   ;==> _GetInfo
;-------------- simplified version of _GetByteString For this Class. ---------------------
Func _GetByteString($sStr, $SnipUnicode)
    Local $sRet, $iLen, $iA, $iLen2, $A2[1]
    ;    On Error Resume Next
    $iLen2 = 0
    If ($SnipUnicode = False) Then
        ReDim $A2[StringLen($sStr) - 1]
        For $iLen = 1 To StringLen($sStr)
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42  ;-- converts 0-byte to *
            $A2[$iLen - 1] = Chr($iA)
        Next
    Else
        ReDim $A2[ (StringLen($sStr) / 2) - 1]
        For $iLen = 1 To StringLen($sStr) Step 2
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42  ;-- converts 0-byte to *
            $A2[$iLen2] = Chr($iA)
            $iLen2 = $iLen2 + 1
        Next
    EndIf
    Return _Join($A2, "")
EndFunc   ;==> _GetByteString
;-------------------------------- Simplified version of _GetArray. -----------------------
Func _GetArray($sStr)
    ConsoleWrite($sStr & @LF)
    Dim $iA, $Len1, $Len2, $AStr[1]
    ;  On Error Resume Next
    $Len1 = StringLen($sStr)
    ReDim $AStr[$Len1 - 1]
    For $iA = 1 To $Len1
        $AStr ($iA - 1) = Asc(StringMid($sStr, $iA, 1))
    Next
    Return $AStr
EndFunc   ;==> _GetArray
;-------------------- return a number from 2 or 4 bytes. ---------------
Func _GetNumFromBytes($ABytes)
    Dim $Num1
    ;    Err.Clear
    ;        On Error Resume Next
    ;_GetNumFromBytes = -1
    $Num1 = ($ABytes[0] + $ABytes[1] * 256)
    If (UBound($ABytes) = 3) Then
        $Num1 = $Num1 + ($ABytes[2] * 65536) + ($ABytes[3] * 16777216)
    EndIf
    Return $Num1
EndFunc   ;==> _GetNumFromBytes
Func _Join($aStrJ, $sDelim = "")
    Local $sTemp
    If IsArray($aStrJ) Then
        For $x = 0 To UBound($aStrJ) - 1
            $sTemp = $sTemp & $aStrJ[$x] & $sDelim
        Next
        Return $sTemp
    EndIf
    SetError(1)
    Return ""
EndFunc   ;==>_Join
Func OnAutoItStart()
;~     If $CmdLine[0] = 0 Then
;~          MsgBox (266288,@ScriptName,"Drop A PE file [EXE-DLL-OCX] onto this script to get version information.")
;~          Exit
;~      EndIf
    ;Global $Arg = $CmdLine[1]
EndFunc   ;==>OnAutoItStart
Func OnAutoItExit()
    $TS = 0 ;-- just in case.
    $FSO = 0; Nothing
EndFunc   ;==>OnAutoItExit
Edited by gafrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Link to comment
Share on other sites

this should get you closer

OK, Using most of your code, I am now able to get to the point where it detects the PE header but gets stuck again.

For some reason the sticking points have been the $FSO.OpenTextFile ($sFilePath, 1)

it does not seem to read null characters which is important for figuring out the location of the PE. the RAW FileOpen is able to read the nulls so I am able to replace them with chr(42) and get the output to look exactly like VBScript and find PE**

Here is what I have so far. it keeps erroring out on line 171 I think because the $FSO.OpenTextFile ($sFilePath, 1) on line 137 is not reading the binary data properly.

;-- This script includes a class and a demo. Drop any PE file onto the script (EXE, DLL, OCX)
;-- to get file properties. The class, ClsProps, is a complete set of all functions needed
;-- get file properties using only VBS and the Textstream object.
;-- The file properties returned are those that are found when a file is right-clicked,
;-- Properties menu is clicked, and Version tab is selected. This information
;-- is included in most PE (portable executable) files.
;-- Thank you to Ed Gruberman (http://www.rjump.com) for help with this code.
;-- He corrected a bug and also worked out the "aspack" variation whereby some
;-- PE files have been compressed and require a different method to find the version info.  j.
;-- NOTE: This script is written to be compact for pasting into scripts. It uses simplified versions of some functions from
;-- the Textstream Binary Ops and Base 64 download, using only the functionality needed to get file version info.,
;--  in order to keep this class as small as possible. If you want to use functions such as _GetArray or _GetByteString
;-- you may want to download the other package. It provides a fairly complete set of methods for working with binary files.
;-- Demo script --------------------
;~ Dim $Arg, cPE, $i2, $AReturn
;~      If WScript.arguments.count = 0 Then
;~         MsgBox( 266288 , @ScriptName, "Drop A PE file [EXE-DLL-OCX] onto this script to get version information.")
;~          WScript.quit
;~      Else
;~          $Arg = WScript.arguments.item(0)
;~      EndIf
Local $Arg, $i2, $AReturn
$Arg = "D:\Temp\WinXP.exe"


Global $FSO, $TS, $sAst, $ANums, $Char1
$sAst = "*"
$Char1 = Chr(1)
$FSO = ObjCreate("Scripting.FileSystemObject")
$i2 = _GetVersionInfo($Arg, $AReturn)
Switch $i2
    Case 1
        MsgBox(266288, @ScriptName, "File path not valid")
    Case 2
        MsgBox(266288, @ScriptName, "Unable to find Resource table header in file.")
    Case 3
        MsgBox(266288, @ScriptName, "Unable to find file version info. in file.")
    Case 4
        MsgBox(266288, @ScriptName, "This is not a PE file.")
    Case 5
        MsgBox(266288, @ScriptName, "This is a 16-bit executable. It is not a PE file.")
    Case 0  ; success
        $s = "Company: " & $AReturn (0) & @CRLF
        $s = $s & "File Description: " & $AReturn (1) & @CRLF
        $s = $s & "File Version: " & $AReturn (2) & @CRLF
        $s = $s & "Product Name: " & $AReturn (3) & @CRLF
        $s = $s & "Copyright: " & $AReturn (4) & @CRLF
        $s = $s & "Original file name: " & $AReturn (5) & @CRLF
        $s = $s & "Installer Engine:  " & $AReturn (6) & @CRLF
        MsgBox(266288, @ScriptName, $Arg & @CRLF & @CRLF & $s)
EndSwitch
;-- End demo script ------------------------------------------------------------
;-- //////////////////////// Start Class:   ClsProps   ///////////////////////////////////////////////
;  Functions in this class. (All functions are needed for getting file version information.)
;   Public Function _GetVersionInfo($sFilePath, $ARet2)  - returns version information For PE files.
;                                                                On success $ARet2 returns array(5) containing version info. strings for file.
;    Function return error codes:    0 = success.      1 = invalid file path.      2 = no .rsrc table listed in section table.
;    3 = failed to find version info.       4 = not a PE file.       5 = file is a 16-bit executable. ("NE" file rather than "PE")
;     Private (internal) functions:
;        _GetArray(StringIn) - convert a string to an array of byte values.
;        _GetByteString(StringIn, $SnipUnicode) - convert a string to a manageable version. If $SnipUnicode = True then get only every 2nd byte.
;        _GetNumFromBytes(array) - takes array of ubound 1 or 3. return numeric value for 2 or 4 bytes.
;----------------////////////  --- BEGIN Class HERE ---  /////////////////////-------------------------------------------
;-- The public function in this class: _GetVersionInfo -----------------------------------------
Func _GetVersionInfo($sFilePath, ByRef $ARet2)  ;-- return array(5)
    Local $ARet, $s1, $sB, $Pt1, $sRes, $A1, $A4[4], $A2[1], $LocRes, $VLocRes, $SizeRes, $iOff, $Boo, $sVerString, $sMarker
    Local $iNum1, $iNum2, $iReadPt, $iNum3, $LocAspack, $VLocAspack, $VIOffset, $ReadOffset, $BooAspack
    ;   On Error Resume Next
;~     If ($FSO.FileExists ($sFilePath) = False) Then
;~         Return 1  ;bad path.
;~     EndIf
    $sRes = ".rsrc"
    $sVerString = "VS_VER"
    $BooAspack = False

    $TS = FileOpen($sFilePath, 4)
    $s1 = FileRead($TS, 2048)
    FileClose($TS)
;~     $TS = $FSO.OpenTextFile ($sFilePath, 1)
;~  $s1 = $TS.Read(2048)
;~  $s1 = String($TS.Read (2048)) ;-- Read first 2 KB.
;~     For $x = 1 To 2048
;~         $s1 = $s1 & String($TS.Read(1)) ;-- Read first 2 KB.
;~     Next
;~     $TS.Close

    ConsoleWrite($s1 & @LF)
;~     $TS = 0
    ConsoleWrite(StringMid($s1, 61, 2) & @LF)
    $A1 = _GetArray(StringMid($s1, 61, 2))  ;-- get number value at offset 60 that points to PE signature address.
    $iNum1 = (_GetNumFromBytes($A1) + 1)     ;-- get offset of "PE00"
    $sB = _GetByteString($s1, False)  ;-- get a workable string with Chr(0) replaced by "*".
    MsgBox(0, "_GetByteString 'AutoIT'", $sB)
    $sMarker = StringMid($sB, $iNum1, 4)
    MsgBox(0, "sMarker 'AutoIT'", $sMarker)
    If ($sMarker <> "PE**") Then
        If StringLeft($sMarker, 2) = "NE" Then
            Return 5  ;-- 16 bit.
        Else
            Return 4  ;-- no PE signature found.
        EndIf
    EndIf
    $Pt1 = StringInStr($sB, $sRes)   ;-- find .rsrc table.
    If ($Pt1 = 0) Then
        Return 2  ;no resource table header found.
    EndIf
    $Pt1 = $Pt1 + 12  ;--  size of raw data is 4 bytes at offset of 16 into the .rsrc table.
    $A1 = _GetArray(StringMid($s1, $Pt1, 12))  ;-- get the same string as a numeric array to Read offset numbers.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff]
    Next
    $VLocRes = _GetNumFromBytes($A4)
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4) ;--size of resource section in bytes.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 8]
    Next
    $LocRes = _GetNumFromBytes($A4)    ;-- offset location of resource section.
    $Pt1 = StringInStr(1, $sB, ".aspack")   ;-- find .rsrc table.
    If ($Pt1 > 0) Then
        $BooAspack = True
        $Pt1 = $Pt1 + 12    ;--  virtual offset is first 4 bytes; raw offset is bytes 9-12.
        $A1 = _GetArray(StringMid($s1, $Pt1, 12))
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff]
        Next
        $VLocAspack = _GetNumFromBytes($A4)
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff + 8]
        Next
        $LocAspack = _GetNumFromBytes($A4)
    EndIf
    
    $Boo = False
    $TS = $FSO.OpenTextFile ($sFilePath, 1)
    $TS.Skip ($LocRes + 12)  ;-- get number of names from bytes 13,14 in top level "Type" directory.
    $s1 = $TS.Read (2)       ;-- Read bytes 13,14 to get number of named resource types.
    $iNum1 = Asc($s1)       ;-- number of names.
    $s1 = $TS.Read (2)       ;-- Read bytes 15,16 to get number of numbered resource types.
    $iNum2 = Asc($s1)       ;-- number of nums.
    If ($iNum2 = 0) Then ;-- no numbered entries. have to quit here.
        $TS.Close
        $TS = 0
        Return 3  ;failed to find version info in resource table.
    EndIf
    If ($iNum1 > 0) Then $TS.Skip ($iNum1 * 8) ;-- Skip past named entries.
    $iReadPt = $LocRes + 16 + ($iNum1 * 8)  ;-- update file offset variable because this will be needed.
    $Boo = False
    For $iOff = 1 To $iNum2
        $s1 = $TS.Read (8)
        $iReadPt = $iReadPt + 8
        If (Asc($s1) = 16) Then  ;-- this is version info. entry.
            $Boo = True
            ExitLoop
        EndIf
    Next
    If ($Boo = False) Then  ;-- have to quit. no version info. entry found.
        $TS.Close
        $TS = 0
        Return 3  ;failed to find version info in resource table.
    EndIf
;~  MsgBox(0, "_GetArray()", "Moving into the Next Section")
    $A1 = _GetArray($s1)  ;-- get a byte array for version info entry at top level.
    $iOff = 0
    $iNum3 = 1
    ;Do
    While 1
        For $iNum1 = 0 To 2  ;-- get offset number to next level from 2nd 4 bytes of entry structure.
            $A4[$iNum1] = $A1[$iNum1 + 4]
        Next
        $A4[3] = 0
        $iNum2 = _GetNumFromBytes($A4)
        If ($A1[7] > 127) Then  ;-- high bit was set in entry offset value, so it;s just a pointer to another pointer.
            $iNum2 = $LocRes + $iNum2 + 16
            $TS.Skip ($iNum2 - $iReadPt)   ;- 1)
            $s1 = $TS.Read (8)
            $iReadPt = $iReadPt + (($iNum2 - $iReadPt) + 8)
            $A1 = _GetArray($s1)
        Else  ;-- this is the offset of version info offset info.!
            $iOff = ($iNum2 + $LocRes)
            ;ExitLoop
            ExitLoop
        EndIf
        $iNum3 = $iNum3 + 1
        If ($iNum3 > 10) Then ExitLoop
    WEnd
    ;Loop
    If ($iOff = 0) Then  ;-- have to quit. no final offset found.
        $TS.Close
        $TS = 0
        Return 3  ;failed to find version info in resource table.
    EndIf
    $TS.Skip ($iOff - $iReadPt)
    $s1 = $TS.Read (8)
    $iReadPt = $iReadPt + (($iOff - $iReadPt) + 8)
    $A1 = _GetArray($s1)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1]
    Next
    $VIOffset = _GetNumFromBytes($A4)  ;--offset of version info. given in .rsrc section.
    $ReadOffset = (($VIOffset - $VLocRes) + $LocRes)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1 + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4)
    $TS.Skip ($ReadOffset - $iReadPt)
    $s1 = $TS.Read ($SizeRes)  ;-- read out the entire FileVersionInfo data area.
    $TS.Close
    $TS = 0
    $sB = _GetByteString($s1, True) ;-- snip unicode.
    $Pt1 = StringInStr(1, $sB, $sVerString)
    If ($Pt1 > 0) Then        ;-- "VS_VER" was found, so process the string and quit.
        $ARet = _ProcessRes($sB)
        $ARet2 = $ARet
        Return 0  ; ok
    ElseIf ($BooAspack = True) Then   ;-- if "VS_VER" was not found but there is an "aspack" section then try that.
        $ReadOffset = (($VIOffset - $VLocAspack) + $LocAspack)  ;-- calculate a new file version info data offset.
        $TS = $FSO.OpenTextFile ($sFilePath, 1)  ;-- The file was closed and is now re-opened here. Keeping the file
        $TS.Skip ($ReadOffset)                            ;-- open "just in case" wouldn;t have helped because the file pointer
        $s1 = $TS.Read ($SizeRes)                     ;-- for this read may be further back thean the pointer was when the file
        $TS.Close                                  ;-- was closed. So rather than try to sort out the read point, the file is just
        $TS = 0                        ;-- opened fresh and Skip is used.
        $sB = _GetByteString($s1, True)
        $Pt1 = StringInStr($sB, $sVerString)
        If ($Pt1 > 0) Then
            $ARet = _ProcessRes($sB)
            $ARet2 = $ARet
            Return 0  ; ok
        Else
            Return 3  ;failed to find version info in resource table.
        EndIf
    Else
        Return 3  ;failed to find version info in resource table.
    EndIf
EndFunc   ;==>_GetVersionInfo
Func _ProcessRes($sDat)
    Dim $AInfo[6]
    ;      On Error Resume Next
    $AInfo[0] = _GetInfo($sDat, "CompanyName")
    $AInfo[1] = _GetInfo($sDat, "FileDescription")
    $AInfo[2] = _GetInfo($sDat, "FileVersion")
    $AInfo[3] = _GetInfo($sDat, "ProductName")
    $AInfo[4] = _GetInfo($sDat, "LegalCopyright")
    $AInfo[5] = _GetInfo($sDat, "OriginalFilename")
    $AInfo[6] = _GetInfo($sDat, "Installer Engine")
    Return $AInfo
EndFunc   ;==> _ProcessRes
Func _GetInfo($sStr, $sVal)
    Dim $Pta, $Ptb, $LenVal, $s4
    ;       On Error Resume Next
    ;    _GetInfo = ""
    $LenVal = StringLen($sVal) + 1  ;-- length of info string: "CompanyName" = 11
    $Pta = StringInStr($sStr, $sVal)  ;-- find string name.
    If ($Pta > 0) Then
        $Pta = $Pta + $LenVal
        ;$Ptb = InStr(($Pta + 1), $sStr, $sAst)   ;-- look for next *. some properties are Name**value** and some are
        $Ptb = StringInStr(StringTrimLeft($sStr, ($Pta + 1)), $sAst)   ;-- look for next *. some properties are Name**value** and some are
        If $Ptb > ($Pta + 2) Then              ;-- Name*value**. So start looking at 3rd character after. If that
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))    ;-- character is * then it;s Name*** which means there;s
            $s4 = StringReplace($s4, $sAst, "")                                           ;--no value for that specific property.
            If StringInStr($s4, $Char1, 0) = 0 Then Return $s4   ;-- check for Chr(1) which seems to be found
        EndIf                             ; between values. If it;s in the string that means there is no value for
        ; this property and function has actually read next property name.
    EndIf
EndFunc   ;==> _GetInfo
;-------------- simplified version of _GetByteString For this Class. ---------------------
Func _GetByteString($sStr, $SnipUnicode)
    Local $sRet, $iLen, $iA, $iLen2, $A2[1]
    ;    On Error Resume Next
    $iLen2 = 0
    If ($SnipUnicode = False) Then
;~      MsgBox(0, "String Length", StringLen($sStr))
        ReDim $A2[StringLen($sStr) + 1]
;~      MsgBox(0, "Ubound", UBound($A2))
        For $iLen = 1 To StringLen($sStr)
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then 
                $iA = 42  ;-- converts 0-byte to *
;~              MsgBox(0, "Found a 0", $iLen)
            EndIf
            $A2[$iLen - 1] = Chr($iA)
        Next
    Else
        ReDim $A2[ (StringLen($sStr) / 2) - 1]
        For $iLen = 1 To StringLen($sStr) Step 2
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42  ;-- converts 0-byte to *
            $A2[$iLen2] = Chr($iA)
            $iLen2 = $iLen2 + 1
        Next
    EndIf
    Return _Join($A2, "")
EndFunc   ;==> _GetByteString
;-------------------------------- Simplified version of _GetArray. -----------------------
Func _GetArray($sStr)
    ConsoleWrite($sStr & @LF)
    Dim $iA, $Len1, $Len2, $AStr[1]
    ;  On Error Resume Next
    $Len1 = StringLen($sStr)
;~  MsgBox(0, "_GetArray()", "String Len:  " & $Len1)
    ReDim $AStr[$Len1]
    For $iA = 1 To $Len1
        $AStr[$iA - 1] = Asc(StringMid($sStr, $iA, 1))
    Next
    Return $AStr
EndFunc   ;==> _GetArray


;-------------------- return a number from 2 or 4 bytes. ---------------
Func _GetNumFromBytes($ABytes)
    Dim $Num1
    ;    Err.Clear
    ;        On Error Resume Next
    ;_GetNumFromBytes = -1
    $Num1 = $ABytes[0] + ($ABytes[1] * 256)
    If (UBound($ABytes) = 3) Then
       $Num1 = $Num1 + ($ABytes[2] * 65536) + ($ABytes[3] * 16777216)
    EndIf
    Return $Num1
EndFunc   ;==> _GetNumFromBytes


Func _Join($aStrJ, $sDelim = "")
    Local $sTemp
    If IsArray($aStrJ) Then
        For $x = 0 To UBound($aStrJ) - 1
            $sTemp = $sTemp & $aStrJ[$x] & $sDelim
        Next
;~         MsgBox(0, "sTemp", $sTemp)
        Return $sTemp
    EndIf
    SetError(1)
    Return ""
EndFunc   ;==>_Join
Func OnAutoItStart()
;~     If $CmdLine[0] = 0 Then
;~          MsgBox (266288,@ScriptName,"Drop A PE file [EXE-DLL-OCX] onto this script to get version information.")
;~          Exit
;~      EndIf
    ;Global $Arg = $CmdLine[1]
EndFunc   ;==>OnAutoItStart
Func OnAutoItExit()
    $TS = 0 ;-- just in case.
    $FSO = 0; Nothing
EndFunc   ;==>OnAutoItExit
Link to comment
Share on other sites

Here's the latest version

;-- This script includes a class and a demo. Drop any PE file onto the script (EXE, DLL, OCX)
;-- to get file properties. The class, ClsProps, is a complete set of all functions needed
;-- get file properties using only VBS and the Textstream object.
;-- The file properties returned are those that are found when a file is right-clicked,
;-- Properties menu is clicked, and Version tab is selected. This information
;-- is included in most PE (portable executable) files.

;-- Thank you to Ed Gruberman (http://www.rjump.com) for help with this code.
;-- He corrected a bug and also worked out the "aspack" variation whereby some
;-- PE files have been compressed and require a different method to find the version info.  j.

;-- NOTE: This script is written to be compact for pasting into scripts. It uses simplified versions of some functions from
;-- the Textstream Binary Ops and Base 64 download, using only the functionality needed to get file version info.,
;--  in order to keep this class as small as possible. If you want to use functions such as _GetArray or _GetByteString
;-- you may want to download the other package. It provides a fairly complete set of methods for working with binary files.

;-- Demo script --------------------
;Converted to AutoItV3   Steve Podhajecki [eltorro] steve@ocotillo.sytes.net

Global $sAst, $ANums
Global $Arg, $i2, $AReturn, $s
;See OnAutoItStart()
;$Arg = "Windows2000-KB914388-x86-ENU.EXE"
;$Arg= "C:\Windows\System32\cmdhere.dll"
;$Arg = "C:\Windows\System32\ZlibTool.ocx"
;$Arg = "C:\Windows\System32\Calc.exe"

$i2 = _GetVersionInfo($Arg, $AReturn)
Switch $i2
    Case 1
        MsgBox(266288, @ScriptName, "File path not valid")
    Case 2
        MsgBox(266288, @ScriptName, "Unable to find Resource table header in file.")
    Case 3
        MsgBox(266288, @ScriptName, "Unable to find file version info. in file.")
    Case 4
        MsgBox(266288, @ScriptName, "This is not a PE file.")
    Case 5
        MsgBox(266288, @ScriptName, "This is a 16-bit executable. It is not a PE file.")
    Case 0  ; success
        $s = "Company: " & $AReturn[0] & @CRLF
        $s = $s & "File Description: " & $AReturn[1] & @CRLF
        $s = $s & "File Version: " & $AReturn[2] & @CRLF
        $s = $s & "Product Name: " & $AReturn[3] & @CRLF
        $s = $s & "Copyright: " & $AReturn[4] & @CRLF
        $s = $s & "Original file name: " & $AReturn[5] & @CRLF
        $s = $s & "Installer Engine:  " & $AReturn[6] & @CRLF
        MsgBox(266288, @ScriptName, $Arg & @CRLF & @CRLF & $s)
EndSwitch

;-- End demo script ------------------------------------------------------------

;-- //////////////////////// Start Class:   ClsProps   ///////////////////////////////////////////////
;
;  Functions in this class. (All functions are needed for getting file version information.)
;
;   Public Function _GetVersionInfo($sFilePath, $ARet2)  - returns version information For PE files.
;                                                                On success $ARet2 returns array(5) containing version info. strings for file.
;    Function return error codes:    0 = success.      1 = invalid file path.      2 = no .rsrc table listed in section table.
;    3 = failed to find version info.       4 = not a PE file.       5 = file is a 16-bit executable. ("NE" file rather than "PE")
;
;     Private (internal) functions:
;        _GetArray(StringIn) - convert a string to an array of byte values.
;        _GetByteString(StringIn, $SnipUnicode) - convert a string to a manageable version. If $SnipUnicode = True then get only every 2nd byte.
;        _GetNumFromBytes(array) - takes array of ubound 1 or 3. return numeric value for 2 or 4 bytes.
;
;
;
;
;
;----------------////////////  --- BEGIN Class HERE ---  /////////////////////-------------------------------------------

Func OnAutoItStart()
    ;uncomment this for drag to or commandline usage.
    If $CmdLine[0] = 0 Then
        MsgBox(266288, @ScriptName, "Drop A PE file [EXE-DLL-OCX] onto this script to get version information." & _
                @CRLF & "Commad Prompt Usage:" & @CRLF & @ScriptName & " " & "myfile.[exe,dll,ocx]")
        Exit
    EndIf
    Global $Arg = $CmdLine[1]
EndFunc   ;==>OnAutoItStart


;-- The public function in this class: _GetVersionInfo -----------------------------------------
Func _GetVersionInfo($sFilePath, ByRef $ARet2)  ;-- return array(5)
    Local $ARet, $s1, $sB, $Pt1, $sRes, $A1, $A4[4], $A2[4], $LocRes, $VLocRes, $SizeRes, $iOff, $Boo, $sVerString, $sMarker
    Local $iNum1, $iNum2, $iReadPt, $iNum3, $LocAspack, $VLocAspack, $VIOffset, $ReadOffset, $BooAspack
    ;   On Error Resume Next
    If Not FileExists($sFilePath) Then
        Return 1  ;bad path.
    EndIf
    $sRes = ".rsrc"
    $sVerString = "VS_VER"
    $BooAspack = False
    
    
    $file = FileOpen($sFilePath, 0)
    $s1 = FileRead($sFilePath, 2048)
    FileClose($file)
    $file = 0
    ;ConsoleWrite($s1)
    $A1 = _GetArray(StringMid($s1, 61, 2))  ;-- get number value at offset 60 that points to PE signature address.
    
    $iNum1 = (_GetNumFromBytes($A1) + 1)     ;-- get offset of "PE00"
    $sB = _GetByteString($s1, False)  ;-- get a workable string with Chr(0) replaced by "*".
    $sMarker = StringMid($sB, $iNum1, 4)
    ;ConsoleWrite("$sMarker ="&$sMarker&@LF)
    If ($sMarker <> "PE**") Then
        If StringLeft($sMarker, 2) = "NE" Then
            Return 5  ;-- 16 bit.
        Else
            Return 4  ;-- no PE signature found.
        EndIf
    EndIf
    
    $Pt1 = StringInStr($sB, $sRes)   ;-- find .rsrc table.
    If ($Pt1 = 0) Then
        Return 2  ;no resource table header found.
    EndIf
    $Pt1 = $Pt1 + 12  ;--  size of raw data is 4 bytes at offset of 16 into the .rsrc table.
    $A1 = _GetArray(StringMid($s1, $Pt1, 12))  ;-- get the same string as a numeric array to Read offset numbers.
    For $iOff = 0 To 3
        ;ConsoleWrite("$iOff ="&$iOff&@LF)
        $A4[$iOff] = $A1[$iOff]
    Next
    $VLocRes = _GetNumFromBytes($A4)
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4) ;--size of resource section in bytes.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 8]
    Next
    $LocRes = _GetNumFromBytes($A4)    ;-- offset location of resource section.
    $Pt1 = StringInStr(1, $sB, ".aspack")   ;-- find .rsrc table.
    If ($Pt1 > 0) Then
        $BooAspack = True
        $Pt1 = $Pt1 + 12    ;--  virtual offset is first 4 bytes; raw offset is bytes 9-12.
        $A1 = _GetArray(StringMid($s1, $Pt1, 12))
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff]
        Next
        $VLocAspack = _GetNumFromBytes($A4)
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff + 8]
        Next
        $LocAspack = _GetNumFromBytes($A4)
    EndIf
    
    $Boo = False
    $file = FileOpen($sFilePath, 0)
    ;MsgBox(0, "$LocRes", "$LocRes+12 =" & $LocRes + 12)
;~     ConsoleWrite("$LocRes+12 =" & $LocRes + 12 & @CRLF)
    _Skip($file, $LocRes + 12)
    $s1 = FileRead($file, 2)  ;-- Read bytes 13,14 to get number of named resource types.
    $iNum1 = Asc($s1)       ;-- number of names.
    ;    ConsoleWrite("$iNum1 =" & $iNum1 & @LF)
    $s2 = FileRead($file, 2)  ;-- Read bytes 15,16 to get number of numbered resource types.
    
    $iNum2 = Asc($s2);-- number of nums.
    ;    ConsoleWrite("$iNum2 =" & $iNum2 & @LF)
    If $iNum2 = 0 Then ;-- no numbered entries. have to quit here.
        Return 3
    EndIf
    
    
    If ($iNum1 > 0) Then _Skip($file, $iNum1 * 8) ;-- Skip past named entries.
    $iReadPt = $LocRes + 16 + ($iNum1 * 8)  ;-- update file offset variable because this will be needed.
    ;ConsoleWrite("$iReadPt ="& $iReadPt&@LF)
    $Boo = False
    For $iOff = 1 To $iNum2
        $s1 = FileRead($file, 8)
        $iReadPt = $iReadPt + 8
        If (Asc($s1) = 16) Then  ;-- this is version info. entry.
            $Boo = True
            ExitLoop
        EndIf
    Next
    If ($Boo = False) Then  ;-- have to quit. no version info. entry found.
        
        ;ConsoleWrite("Return point 1" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
    
    $A1 = _GetArray($s1)  ;-- get a byte array for version info entry at top level.
    ;ConsoleWrite("Ubound>>"&UBound($A1))
    $iOff = 0
    $iNum3 = 1
    ;Do
    While 1
        For $iNum1 = 0 To 2  ;-- get offset number to next level from 2nd 4 bytes of entry structure.
            $A4[$iNum1] = $A1[$iNum1 + 4]
        Next
        $A4[3] = 0
        $iNum2 = _GetNumFromBytes($A4)
        
        If ($A1[7] > 127) Then  ;-- high bit was set in entry offset value, so it;s just a pointer to another pointer.
            $iNum2 = $LocRes + $iNum2 + 16
            _Skip($file, $iNum2 - $iReadPt)   ;- 1)
            $s1 = FileRead($file, 8)
            $iReadPt = $iReadPt + (($iNum2 - $iReadPt) + 8)
            $A1 = _GetArray($s1)
        Else  ;-- this is the offset of version info offset info.!
            $iOff = ($iNum2 + $LocRes)
            ;ExitLoop
            ExitLoop
        EndIf
        $iNum3 = $iNum3 + 1
        If ($iNum3 > 10) Then ExitLoop
    WEnd
    ;Loop
    If ($iOff = 0) Then  ;-- have to quit. no final offset found.
        ;ConsoleWrite("Return point 2" & @LF)
        Return 3  ;failed to find version info in resource table.
        
    EndIf
    _Skip($file, $iOff - $iReadPt)
    $s1 = FileRead($file, 8)
    $iReadPt = $iReadPt + (($iOff - $iReadPt) + 8)
    $A1 = _GetArray($s1)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1]
    Next
    $VIOffset = _GetNumFromBytes($A4)  ;--offset of version info. given in .rsrc section.
    $ReadOffset = (($VIOffset - $VLocRes) + $LocRes)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1 + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4)
    _Skip($file, $ReadOffset - $iReadPt)
    $s1 = FileRead($file, $SizeRes)  ;-- read out the entire FileVersionInfo data area.
    FileClose($file)
    $file = 0
    $sB = _GetByteString($s1, True) ;-- snip unicode.
    $Pt1 = StringInStr($sB, $sVerString)
    If ($Pt1 > 0) Then        ;-- "VS_VER" was found, so process the string and quit.
        $ARet = _ProcessRes($sB)
        $ARet2 = $ARet
        Return 0  ; ok
    ElseIf ($BooAspack = True) Then   ;-- if "VS_VER" was not found but there is an "aspack" section then try that.
        $ReadOffset = (($VIOffset - $VLocAspack) + $LocAspack)  ;-- calculate a new file version info data offset.
        $file = FileOpen($sFilePath, 0)  ;-- The file was closed and is now re-opened here. Keeping the file
        _Skip($file, $ReadOffset)                            ;-- open "just in case" wouldn;t have helped because the file pointer
        $s1 = FileRead($file, $SizeRes)                     ;-- for this read may be further back thean the pointer was when the file
        FileClose($file) ;-- was closed. So rather than try to sort out the read point, the file is just
        $file = 0;-- opened fresh and Skip is used.
        $sB = _GetByteString($s1, True)
        $Pt1 = StringInStr($sB, $sVerString)
        If ($Pt1 > 0) Then
            $ARet = _ProcessRes($sB)
            $ARet2 = $ARet
            Return 0  ; ok
        Else
            ;ConsoleWrite("Return point 3" & @LF)
            Return 3  ;failed to find version info in resource table.
        EndIf
    Else
        ;ConsoleWrite("Return point 4" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
EndFunc   ;==>_GetVersionInfo

Func _ProcessRes($sDat)
    Dim $AInfo[7]
    ;      On Error Resume Next
    $AInfo[0] = _GetInfo($sDat, "CompanyName")
    $AInfo[1] = _GetInfo($sDat, "FileDescription")
    $AInfo[2] = _GetInfo($sDat, "FileVersion")
    $AInfo[3] = _GetInfo($sDat, "ProductName")
    $AInfo[4] = _GetInfo($sDat, "LegalCopyright")
    $AInfo[5] = _GetInfo($sDat, "OriginalFilename")
    $AInfo[6] = _GetInfo($sDat, "Installer Engine")
    Return $AInfo
EndFunc   ;==>_ProcessRes

Func _GetInfo($sStr, $sVal)
    ; had to rewrite this function because of incompatiblities
    ;between AutoIt3 and Vb string functions.
    Dim $Pta, $Ptb, $LenVal, $s4, $occurance = 1
    $LenVal = StringLen($sVal) + 1  ;-- length of info string: "CompanyName" = 11
    $Pta = StringInStr($sStr, $sVal)  ;-- find string name.
    If ($Pta > 0) Then
        $Pta = $Pta + $LenVal
        $Ptb = $Pta + StringInStr(StringMid($sStr, $Pta + 1), "*")
        If $Ptb > ($Pta + 2) Then              ;-- Name*value**. So start looking at 3rd character after. If that
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))    ;-- character is * then it's Name*** which means there's
            $s4 = StringReplace($s4, "*", "")                                           ;--no value for that specific property.
            If StringInStr($s4, Chr(1), 1) = 0 Then Return $s4   ;-- check for Chr(1) which seems to be found
        EndIf                             ; between values. If it's in the string that means there is no value for
        
    EndIf
    Return ""
EndFunc   ;==>_GetInfo
;-------------- simplified version of _GetByteString For this Class. ---------------------
Func _GetByteString($sStr, $SnipUnicode)
    Local $sRet, $iLen, $iA, $iLen2, $A2[2]
    ;    On Error Resume Next
    $iLen2 = 0
    If ($SnipUnicode = False) Then
        ReDim $A2[StringLen($sStr)]
        For $iLen = 1 To StringLen($sStr)
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            ;If UBound($A2) > $iLen - 1 Then
            $A2[$iLen - 1] = Chr($iA)
        Next
    Else
        ReDim $A2[ (StringLen($sStr) / 2)]
        For $iLen = 1 To StringLen($sStr) Step 2
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            $A2[$iLen2] = Chr($iA)
            $iLen2 = $iLen2 + 1
        Next
    EndIf
    Return _Join($A2, "")
EndFunc   ;==>_GetByteString
;-------------------------------- Simplified version of _GetArray. -----------------------
Func _GetArray($sStr)
    Dim $iA, $Len1, $Len2, $AStr[2]
    ;  On Error Resume Next
    $Len1 = StringLen($sStr)
    ConsoleWrite("$Len1 = " & $Len1 & @LF)
    If $Len1 > 1 Then ReDim $AStr[ ($Len1)]
    For $iA = 1 To $Len1
        $AStr[$iA - 1] = Asc(StringMid($sStr, $iA, 1))
    Next
    Return $AStr
EndFunc   ;==>_GetArray
;-------------------- return a number from 2 or 4 bytes. ---------------
Func _GetNumFromBytes($ABytes)
    Dim $Num1
    ;    Err.Clear
    ;        On Error Resume Next
    ;_GetNumFromBytes = -1
    If UBound($ABytes) > 1 Then
        $Num1 = ($ABytes[0] + $ABytes[1] * 256)
        If (UBound($ABytes) > 3) Then
            $Num1 = $Num1 + ($ABytes[2] * 65536) + ($ABytes[3] * 16777216)
        EndIf
        Return $Num1
    EndIf
EndFunc   ;==>_GetNumFromBytes

Func _Join($aStrJ, $sDelim = "")
    ;mimic VB Join command (array to string with delimiter)
    Local $sTemp
    If IsArray($aStrJ) Then
        For $x = 0 To UBound($aStrJ) - 1
            $sTemp = $sTemp & $aStrJ[$x] & $sDelim
        Next
        ;ConsoleWrite("Join $sTemp =" & $sTemp & @LF)
        Return $sTemp
    EndIf
    SetError(1)
    Return ""
EndFunc   ;==>_Join

Func _Skip($hfile, $bytes)
    ;mimic FSO.skip
    Local $temp = FileRead($hfile, $bytes)
    If @error Then Return 0
    Return 1
EndFunc   ;==>_Skip

Please post any bugs.

Regards,

eltorro

Edit: Removed exta bbcode tag

Edited by eltorro
Link to comment
Share on other sites

Here's the latest version

Excelent!!! :D

works Great eltorro.

Now I just have to integrate that in with my main script and I'm all done.

Oh, and if you change say $AInfo[0] = _GetInfo($sDat, "CompanyName") to "Applies to" it will give you the Operating Systems that the patch will work on. "Returns "" if it's not an OS patch" I tested this on some patches all the way back to 2004 with no problems.

Thanks,

Mike

Link to comment
Share on other sites

I have to agreee great job, only problem I found when i was playing around with it this morning was the file version wasn't getting populated.

I know the file I was testing has a version 1.0.0.0 or in the file it reads 1

hadn't had time to look at the logic that gets the info, but here was a quick test to see what information I could retrieve.

Edit: Fixed problem if FileVersion is 1

;-- This script includes a class and a demo. Drop any PE file onto the script (EXE, DLL, OCX)
;-- to get file properties. The class, ClsProps, is a complete set of all functions needed
;-- get file properties using only VBS and the Textstream object.
;-- The file properties returned are those that are found when a file is right-clicked,
;-- Properties menu is clicked, and Version tab is selected. This information
;-- is included in most PE (portable executable) files.

;-- Thank you to Ed Gruberman (http://www.rjump.com) for help with this code.
;-- He corrected a bug and also worked out the "aspack" variation whereby some
;-- PE files have been compressed and require a different method to find the version info.  j.

;-- NOTE: This script is written to be compact for pasting into scripts. It uses simplified versions of some functions from
;-- the Textstream Binary Ops and Base 64 download, using only the functionality needed to get file version info.,
;--  in order to keep this class as small as possible. If you want to use functions such as _GetArray or _GetByteString
;-- you may want to download the other package. It provides a fairly complete set of methods for working with binary files.

;-- Demo script --------------------
;Converted to AutoItV3   Steve Podhajecki [eltorro] steve@ocotillo.sytes.net

Global $sAst, $ANums
Global $Arg, $i2, $AReturn, $s
;See OnAutoItStart()
;$Arg = "Windows2000-KB914388-x86-ENU.EXE"
;$Arg= "C:\Windows\System32\cmdhere.dll"
;$Arg = "C:\Windows\System32\ZlibTool.ocx"
;$Arg = "C:\Windows\System32\Calc.exe"

$i2 = _GetVersionInfo($Arg, $AReturn)
Switch $i2
    Case 1
        MsgBox(266288, @ScriptName, "File path not valid")
    Case 2
        MsgBox(266288, @ScriptName, "Unable to find Resource table header in file.")
    Case 3
        MsgBox(266288, @ScriptName, "Unable to find file version info. in file.")
    Case 4
        MsgBox(266288, @ScriptName, "This is not a PE file.")
    Case 5
        MsgBox(266288, @ScriptName, "This is a 16-bit executable. It is not a PE file.")
    Case 0  ; success
        $s = "Company: " & $AReturn[0] & @CRLF
        $s = $s & "File Description: " & $AReturn[1] & @CRLF
        $s = $s & "File Version: " & $AReturn[2] & @CRLF
        $s = $s & "Product Name: " & $AReturn[3] & @CRLF
        $s = $s & "Copyright: " & $AReturn[4] & @CRLF
        $s = $s & "Original file name: " & $AReturn[5] & @CRLF
        $s = $s & "Installer Engine:  " & $AReturn[6] & @CRLF
        $s = $s & "Applies to: " & $AReturn[7] & @CRLF
        $s = $s & "Build Date: " & $AReturn[8] & @CRLF
        $s = $s & "Installation Type: " & $AReturn[9] & @CRLF
        $s = $s & "Installer Version: " & $AReturn[10] & @CRLF
        $s = $s & "Internal Name: " & $AReturn[11] & @CRLF
        $s = $s & "KB Article Name: " & $AReturn[12] & @CRLF
        $s = $s & "Support Link: " & $AReturn[13] & @CRLF
        $s = $s & "Package Type: " & $AReturn[14] & @CRLF
        $s = $s & "Proc. Architecture: " & $AReturn[15] & @CRLF
        $s = $s & "Self-Extractor Version: " & $AReturn[16] & @CRLF
        $s = $s & "Display Name: " & $AReturn[17] & @CRLF
        MsgBox(266288, @ScriptName, $Arg & @CRLF & @CRLF & $s)
EndSwitch

;-- End demo script ------------------------------------------------------------

;-- //////////////////////// Start Class:   ClsProps   ///////////////////////////////////////////////
;
;  Functions in this class. (All functions are needed for getting file version information.)
;
;   Public Function _GetVersionInfo($sFilePath, $ARet2)  - returns version information For PE files.
;                                                                On success $ARet2 returns array(5) containing version info. strings for file.
;    Function return error codes:    0 = success.      1 = invalid file path.      2 = no .rsrc table listed in section table.
;    3 = failed to find version info.       4 = not a PE file.       5 = file is a 16-bit executable. ("NE" file rather than "PE")
;
;     Private (internal) functions:
;        _GetArray(StringIn) - convert a string to an array of byte values.
;        _GetByteString(StringIn, $SnipUnicode) - convert a string to a manageable version. If $SnipUnicode = True then get only every 2nd byte.
;        _GetNumFromBytes(array) - takes array of ubound 1 or 3. return numeric value for 2 or 4 bytes.
;
;
;
;
;
;----------------////////////  --- BEGIN Class HERE ---  /////////////////////-------------------------------------------

Func OnAutoItStart()
    ;uncomment this for drag to or commandline usage.
    If $CmdLine[0] = 0 Then
        MsgBox(266288, @ScriptName, "Drop A PE file [EXE-DLL-OCX] onto this script to get version information." & _
                @CRLF & "Commad Prompt Usage:" & @CRLF & @ScriptName & " " & "myfile.[exe,dll,ocx]")
        Exit
    EndIf
    Global $Arg = $CmdLine[1]
EndFunc   ;==>OnAutoItStart


;-- The public function in this class: _GetVersionInfo -----------------------------------------
Func _GetVersionInfo($sFilePath, ByRef $ARet2)  ;-- return array(5)
    Local $ARet, $s1, $sB, $Pt1, $sRes, $A1, $A4[4], $A2[4], $LocRes, $VLocRes, $SizeRes, $iOff, $Boo, $sVerString, $sMarker
    Local $iNum1, $iNum2, $iReadPt, $iNum3, $LocAspack, $VLocAspack, $VIOffset, $ReadOffset, $BooAspack
    ;   On Error Resume Next
    If Not FileExists($sFilePath) Then
        Return 1  ;bad path.
    EndIf
    $sRes = ".rsrc"
    $sVerString = "VS_VER"
    $BooAspack = False
    
    
    $file = FileOpen($sFilePath, 0)
    $s1 = FileRead($sFilePath, 2048)
    FileClose($file)
    $file = 0
    ;ConsoleWrite($s1)
    $A1 = _GetArray(StringMid($s1, 61, 2))  ;-- get number value at offset 60 that points to PE signature address.
    
    $iNum1 = (_GetNumFromBytes($A1) + 1)     ;-- get offset of "PE00"
    $sB = _GetByteString($s1, False)  ;-- get a workable string with Chr(0) replaced by "*".
    $sMarker = StringMid($sB, $iNum1, 4)
    ;ConsoleWrite("$sMarker ="&$sMarker&@LF)
    If ($sMarker <> "PE**") Then
        If StringLeft($sMarker, 2) = "NE" Then
            Return 5  ;-- 16 bit.
        Else
            Return 4  ;-- no PE signature found.
        EndIf
    EndIf
    
    $Pt1 = StringInStr($sB, $sRes)   ;-- find .rsrc table.
    If ($Pt1 = 0) Then
        Return 2  ;no resource table header found.
    EndIf
    $Pt1 = $Pt1 + 12  ;--  size of raw data is 4 bytes at offset of 16 into the .rsrc table.
    $A1 = _GetArray(StringMid($s1, $Pt1, 12))  ;-- get the same string as a numeric array to Read offset numbers.
    For $iOff = 0 To 3
        ;ConsoleWrite("$iOff ="&$iOff&@LF)
        $A4[$iOff] = $A1[$iOff]
    Next
    $VLocRes = _GetNumFromBytes($A4)
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4) ;--size of resource section in bytes.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 8]
    Next
    $LocRes = _GetNumFromBytes($A4)    ;-- offset location of resource section.
    $Pt1 = StringInStr(1, $sB, ".aspack")   ;-- find .rsrc table.
    If ($Pt1 > 0) Then
        $BooAspack = True
        $Pt1 = $Pt1 + 12    ;--  virtual offset is first 4 bytes; raw offset is bytes 9-12.
        $A1 = _GetArray(StringMid($s1, $Pt1, 12))
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff]
        Next
        $VLocAspack = _GetNumFromBytes($A4)
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff + 8]
        Next
        $LocAspack = _GetNumFromBytes($A4)
    EndIf
    
    $Boo = False
    $file = FileOpen($sFilePath, 0)
    ;MsgBox(0, "$LocRes", "$LocRes+12 =" & $LocRes + 12)
;~     ConsoleWrite("$LocRes+12 =" & $LocRes + 12 & @CRLF)
    _Skip($file, $LocRes + 12)
    $s1 = FileRead($file, 2)  ;-- Read bytes 13,14 to get number of named resource types.
    $iNum1 = Asc($s1)       ;-- number of names.
    ;    ConsoleWrite("$iNum1 =" & $iNum1 & @LF)
    $s2 = FileRead($file, 2)  ;-- Read bytes 15,16 to get number of numbered resource types.
    
    $iNum2 = Asc($s2);-- number of nums.
    ;    ConsoleWrite("$iNum2 =" & $iNum2 & @LF)
    If $iNum2 = 0 Then ;-- no numbered entries. have to quit here.
        Return 3
    EndIf
    
    
    If ($iNum1 > 0) Then _Skip($file, $iNum1 * 8) ;-- Skip past named entries.
    $iReadPt = $LocRes + 16 + ($iNum1 * 8)  ;-- update file offset variable because this will be needed.
    ;ConsoleWrite("$iReadPt ="& $iReadPt&@LF)
    $Boo = False
    For $iOff = 1 To $iNum2
        $s1 = FileRead($file, 8)
        $iReadPt = $iReadPt + 8
        If (Asc($s1) = 16) Then  ;-- this is version info. entry.
            $Boo = True
            ExitLoop
        EndIf
    Next
    If ($Boo = False) Then  ;-- have to quit. no version info. entry found.
        
        ;ConsoleWrite("Return point 1" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
    
    $A1 = _GetArray($s1)  ;-- get a byte array for version info entry at top level.
    ;ConsoleWrite("Ubound>>"&UBound($A1))
    $iOff = 0
    $iNum3 = 1
    ;Do
    While 1
        For $iNum1 = 0 To 2  ;-- get offset number to next level from 2nd 4 bytes of entry structure.
            $A4[$iNum1] = $A1[$iNum1 + 4]
        Next
        $A4[3] = 0
        $iNum2 = _GetNumFromBytes($A4)
        
        If ($A1[7] > 127) Then  ;-- high bit was set in entry offset value, so it;s just a pointer to another pointer.
            $iNum2 = $LocRes + $iNum2 + 16
            _Skip($file, $iNum2 - $iReadPt)   ;- 1)
            $s1 = FileRead($file, 8)
            $iReadPt = $iReadPt + (($iNum2 - $iReadPt) + 8)
            $A1 = _GetArray($s1)
        Else  ;-- this is the offset of version info offset info.!
            $iOff = ($iNum2 + $LocRes)
            ;ExitLoop
            ExitLoop
        EndIf
        $iNum3 = $iNum3 + 1
        If ($iNum3 > 10) Then ExitLoop
    WEnd
    ;Loop
    If ($iOff = 0) Then  ;-- have to quit. no final offset found.
        ;ConsoleWrite("Return point 2" & @LF)
        Return 3  ;failed to find version info in resource table.
        
    EndIf
    _Skip($file, $iOff - $iReadPt)
    $s1 = FileRead($file, 8)
    $iReadPt = $iReadPt + (($iOff - $iReadPt) + 8)
    $A1 = _GetArray($s1)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1]
    Next
    $VIOffset = _GetNumFromBytes($A4)  ;--offset of version info. given in .rsrc section.
    $ReadOffset = (($VIOffset - $VLocRes) + $LocRes)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1 + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4)
    _Skip($file, $ReadOffset - $iReadPt)
    $s1 = FileRead($file, $SizeRes)  ;-- read out the entire FileVersionInfo data area.
    FileClose($file)
    $file = 0
    $sB = _GetByteString($s1, True) ;-- snip unicode.
    $Pt1 = StringInStr($sB, $sVerString)
    If ($Pt1 > 0) Then        ;-- "VS_VER" was found, so process the string and quit.
        $ARet = _ProcessRes($sB)
        $ARet2 = $ARet
        Return 0  ; ok
    ElseIf ($BooAspack = True) Then   ;-- if "VS_VER" was not found but there is an "aspack" section then try that.
        $ReadOffset = (($VIOffset - $VLocAspack) + $LocAspack)  ;-- calculate a new file version info data offset.
        $file = FileOpen($sFilePath, 0)  ;-- The file was closed and is now re-opened here. Keeping the file
        _Skip($file, $ReadOffset)                            ;-- open "just in case" wouldn;t have helped because the file pointer
        $s1 = FileRead($file, $SizeRes)                     ;-- for this read may be further back thean the pointer was when the file
        FileClose($file) ;-- was closed. So rather than try to sort out the read point, the file is just
        $file = 0;-- opened fresh and Skip is used.
        $sB = _GetByteString($s1, True)
        $Pt1 = StringInStr($sB, $sVerString)
        If ($Pt1 > 0) Then
            $ARet = _ProcessRes($sB)
            $ARet2 = $ARet
            Return 0  ; ok
        Else
            ;ConsoleWrite("Return point 3" & @LF)
            Return 3  ;failed to find version info in resource table.
        EndIf
    Else
        ;ConsoleWrite("Return point 4" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
EndFunc   ;==>_GetVersionInfo

Func _ProcessRes($sDat)
    Dim $AInfo[18]
    ;      On Error Resume Next
    $AInfo[0] = _GetInfo($sDat, "CompanyName")
    $AInfo[1] = _GetInfo($sDat, "FileDescription")
    $AInfo[2] = _GetInfo($sDat, "FileVersion")
    $AInfo[3] = _GetInfo($sDat, "ProductName")
    $AInfo[4] = _GetInfo($sDat, "LegalCopyright")
    $AInfo[5] = _GetInfo($sDat, "OriginalFilename")
    $AInfo[6] = _GetInfo($sDat, "Installer Engine")
    $AInfo[7] = _GetInfo($sDat, "Applies to")
    $AInfo[8] = _GetInfo($sDat, "Build Date")
    $AInfo[9] = _GetInfo($sDat, "Installation Type")
    $AInfo[10] = _GetInfo($sDat, "Installer Version")
    $AInfo[11] = _GetInfo($sDat, "InternalName")
    $AInfo[12] = _GetInfo($sDat, "KB Article Number")
    $AInfo[13] = _GetInfo($sDat, "Support Link")
    $AInfo[14] = _GetInfo($sDat, "Package Type")
    $AInfo[15] = _GetInfo($sDat, "Proc. Architecture")
    $AInfo[16] = _GetInfo($sDat, "Self-Extractor Version")
    $AInfo[17] = _GetInfo($sDat, "DisplayName")
    Return $AInfo
EndFunc   ;==>_ProcessRes

Func _GetInfo($sStr, $sVal)
    ; had to rewrite this function because of incompatiblities
    ;between AutoIt3 and Vb string functions.
    Dim $Pta, $Ptb, $LenVal, $s4, $occurance = 1
    $LenVal = StringLen($sVal) + 1  ;-- length of info string: "CompanyName" = 11
    $Pta = StringInStr($sStr, $sVal)  ;-- find string name.
    If ($Pta > 0) Then
        $Pta = $Pta + $LenVal
        $Ptb = $Pta + StringInStr(StringMid($sStr, $Pta + 1), "*")
;~        ConsoleWrite(StringMid($sStr, $Pta + 1) & @LF)
        If $Ptb > ($Pta + 2) Or ($Ptb = ($Pta + 2) And $sVal = "FileVersion") Then              ;-- Name*value**. So start looking at 3rd character after. If that
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))    ;-- character is * then it's Name*** which means there's
            $s4 = StringReplace($s4, "*", "")                                           ;--no value for that specific property.
            If StringInStr($s4, Chr(1), 1) = 0 Then Return $s4   ;-- check for Chr(1) which seems to be found
        EndIf                             ; between values. If it's in the string that means there is no value for
        
    EndIf
    Return ""
EndFunc   ;==>_GetInfo
;-------------- simplified version of _GetByteString For this Class. ---------------------
Func _GetByteString($sStr, $SnipUnicode)
    Local $sRet, $iLen, $iA, $iLen2, $A2[2]
    ;    On Error Resume Next
    $iLen2 = 0
    If ($SnipUnicode = False) Then
        ReDim $A2[StringLen($sStr) ]
        For $iLen = 1 To StringLen($sStr)
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            ;If UBound($A2) > $iLen - 1 Then
            $A2[$iLen - 1] = Chr($iA)
        Next
    Else
        ReDim $A2[ (StringLen($sStr) / 2) ]
        For $iLen = 1 To StringLen($sStr) Step 2
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            $A2[$iLen2] = Chr($iA)
            $iLen2 = $iLen2 + 1
        Next
    EndIf
    Return _Join($A2, "")
EndFunc   ;==>_GetByteString
;-------------------------------- Simplified version of _GetArray. -----------------------
Func _GetArray($sStr)
    Dim $iA, $Len1, $Len2, $AStr[2]
    ;  On Error Resume Next
    $Len1 = StringLen($sStr)
    If $Len1 > 1 Then ReDim $AStr[ ($Len1) ]
    For $iA = 1 To $Len1
        $AStr[$iA - 1] = Asc(StringMid($sStr, $iA, 1))
    Next
    Return $AStr
EndFunc   ;==>_GetArray
;-------------------- return a number from 2 or 4 bytes. ---------------
Func _GetNumFromBytes($ABytes)
    Dim $Num1
    ;    Err.Clear
    ;        On Error Resume Next
    ;_GetNumFromBytes = -1
    If UBound($ABytes) > 1 Then
        $Num1 = ($ABytes[0] + $ABytes[1] * 256)
        If (UBound($ABytes) > 3) Then
            $Num1 = $Num1 + ($ABytes[2] * 65536) + ($ABytes[3] * 16777216)
        EndIf
        Return $Num1
    EndIf
EndFunc   ;==>_GetNumFromBytes

Func _Join($aStrJ, $sDelim = "")
    ;mimic VB Join command (array to string with delimiter)
    Local $sTemp
    If IsArray($aStrJ) Then
        For $x = 0 To UBound($aStrJ) - 1
            $sTemp = $sTemp & $aStrJ[$x] & $sDelim
        Next
        ;ConsoleWrite("Join $sTemp =" & $sTemp & @LF)
        Return $sTemp
    EndIf
    SetError(1)
    Return ""
EndFunc   ;==>_Join

Func _Skip($hfile, $bytes)
    ;mimic FSO.skip
    Local $temp = FileRead($hfile, $bytes)
    If @error Then Return 0
    Return 1
EndFunc   ;==>_Skip
Edited by gafrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Link to comment
Share on other sites

Just for curiosity, what does the vbscript return on the same file?

Link to comment
Share on other sites

Just for curiosity, what does the vbscript return on the same file?

Same problem in vb script, if the version number is a single digit it appears to be a problem that was overlooked, I think I resolved that problem.

I decided to make it a little more generic, just change the $props array to what you want to collect.

;-- This script includes a class and a demo. Drop any PE file onto the script (EXE, DLL, OCX)
;-- to get file properties. The class, ClsProps, is a complete set of all functions needed
;-- get file properties using only VBS and the Textstream object.
;-- The file properties returned are those that are found when a file is right-clicked,
;-- Properties menu is clicked, and Version tab is selected. This information
;-- is included in most PE (portable executable) files.

;-- Thank you to Ed Gruberman (http://www.rjump.com) for help with this code.
;-- He corrected a bug and also worked out the "aspack" variation whereby some
;-- PE files have been compressed and require a different method to find the version info.  j.

;-- NOTE: This script is written to be compact for pasting into scripts. It uses simplified versions of some functions from
;-- the Textstream Binary Ops and Base 64 download, using only the functionality needed to get file version info.,
;--  in order to keep this class as small as possible. If you want to use functions such as _GetArray or _GetByteString
;-- you may want to download the other package. It provides a fairly complete set of methods for working with binary files.

;-- Demo script --------------------
;Converted to AutoItV3   Steve Podhajecki [eltorro] steve@ocotillo.sytes.net

Global $sAst, $ANums
Global $Arg, $i2, $AReturn, $s

Global $props[18] = ["CompanyName", "FileDescription", "FileVersion", "ProductName", "LegalCopyright", _
        "OriginalFilename", "Installer Engine", "Applies to", "Build Date", "Installation Type", _
        "Installer Version", "InternalName", "KB Article Number", "Support Link", "Package Type", _
        "Proc. Architecture", "Self-Extractor Version", "DisplayName"]
;See OnAutoItStart()
;$Arg = "Windows2000-KB914388-x86-ENU.EXE"
;$Arg= "C:\Windows\System32\cmdhere.dll"
;$Arg = "C:\Windows\System32\ZlibTool.ocx"
;$Arg = "C:\Windows\System32\Calc.exe"

$i2 = _GetVersionInfo($Arg, $AReturn)
Switch $i2
    Case 1
        MsgBox(266288, @ScriptName, "File path not valid")
    Case 2
        MsgBox(266288, @ScriptName, "Unable to find Resource table header in file.")
    Case 3
        MsgBox(266288, @ScriptName, "Unable to find file version info. in file.")
    Case 4
        MsgBox(266288, @ScriptName, "This is not a PE file.")
    Case 5
        MsgBox(266288, @ScriptName, "This is a 16-bit executable. It is not a PE file.")
    Case 0  ; success
        $s = ""
        For $x = 0 To UBound($props) - 1
            $s &= $props[$x] & ": " & $AReturn[$x] & @CRLF
        Next
        MsgBox(266288, @ScriptName, $Arg & @CRLF & @CRLF & $s)
EndSwitch

;-- End demo script ------------------------------------------------------------

;-- //////////////////////// Start Class:   ClsProps   ///////////////////////////////////////////////
;
;  Functions in this class. (All functions are needed for getting file version information.)
;
;   Public Function _GetVersionInfo($sFilePath, $ARet2)  - returns version information For PE files.
;                                                                On success $ARet2 returns array(5) containing version info. strings for file.
;    Function return error codes:    0 = success.      1 = invalid file path.      2 = no .rsrc table listed in section table.
;    3 = failed to find version info.       4 = not a PE file.       5 = file is a 16-bit executable. ("NE" file rather than "PE")
;
;     Private (internal) functions:
;        _GetArray(StringIn) - convert a string to an array of byte values.
;        _GetByteString(StringIn, $SnipUnicode) - convert a string to a manageable version. If $SnipUnicode = True then get only every 2nd byte.
;        _GetNumFromBytes(array) - takes array of ubound 1 or 3. return numeric value for 2 or 4 bytes.
;
;
;
;
;
;----------------////////////  --- BEGIN Class HERE ---  /////////////////////-------------------------------------------

Func OnAutoItStart()
    ;uncomment this for drag to or commandline usage.
    If $CmdLine[0] = 0 Then
        MsgBox(266288, @ScriptName, "Drop A PE file [EXE-DLL-OCX] onto this script to get version information." & _
                @CRLF & "Commad Prompt Usage:" & @CRLF & @ScriptName & " " & "myfile.[exe,dll,ocx]")
        Exit
    EndIf
    Global $Arg = $CmdLine[1]
EndFunc   ;==>OnAutoItStart


;-- The public function in this class: _GetVersionInfo -----------------------------------------
Func _GetVersionInfo($sFilePath, ByRef $ARet2)  ;-- return array(5)
    Local $ARet, $s1, $sB, $Pt1, $sRes, $A1, $A4[4], $A2[4], $LocRes, $VLocRes, $SizeRes, $iOff, $Boo, $sVerString, $sMarker
    Local $iNum1, $iNum2, $iReadPt, $iNum3, $LocAspack, $VLocAspack, $VIOffset, $ReadOffset, $BooAspack
    ;   On Error Resume Next
    If Not FileExists($sFilePath) Then
        Return 1  ;bad path.
    EndIf
    $sRes = ".rsrc"
    $sVerString = "VS_VER"
    $BooAspack = False
    
    
    $file = FileOpen($sFilePath, 0)
    $s1 = FileRead($sFilePath, 2048)
    FileClose($file)
    $file = 0
    ;ConsoleWrite($s1)
    $A1 = _GetArray(StringMid($s1, 61, 2))  ;-- get number value at offset 60 that points to PE signature address.
    
    $iNum1 = (_GetNumFromBytes($A1) + 1)     ;-- get offset of "PE00"
    $sB = _GetByteString($s1, False)  ;-- get a workable string with Chr(0) replaced by "*".
    $sMarker = StringMid($sB, $iNum1, 4)
;~  ConsoleWrite("$sMarker ="&$sMarker&@LF)
    If ($sMarker <> "PE**") Then
        If StringLeft($sMarker, 2) = "NE" Then
            Return 5  ;-- 16 bit.
        Else
            Return 4  ;-- no PE signature found.
        EndIf
    EndIf
    
    $Pt1 = StringInStr($sB, $sRes)   ;-- find .rsrc table.
    If ($Pt1 = 0) Then
        Return 2  ;no resource table header found.
    EndIf
    $Pt1 = $Pt1 + 12  ;--  size of raw data is 4 bytes at offset of 16 into the .rsrc table.
    $A1 = _GetArray(StringMid($s1, $Pt1, 12))  ;-- get the same string as a numeric array to Read offset numbers.
    For $iOff = 0 To 3
        ;ConsoleWrite("$iOff ="&$iOff&@LF)
        $A4[$iOff] = $A1[$iOff]
    Next
    $VLocRes = _GetNumFromBytes($A4)
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4) ;--size of resource section in bytes.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 8]
    Next
    $LocRes = _GetNumFromBytes($A4)    ;-- offset location of resource section.
    $Pt1 = StringInStr(1, $sB, ".aspack")   ;-- find .rsrc table.
    If ($Pt1 > 0) Then
        $BooAspack = True
        $Pt1 = $Pt1 + 12    ;--  virtual offset is first 4 bytes; raw offset is bytes 9-12.
        $A1 = _GetArray(StringMid($s1, $Pt1, 12))
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff]
        Next
        $VLocAspack = _GetNumFromBytes($A4)
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff + 8]
        Next
        $LocAspack = _GetNumFromBytes($A4)
    EndIf
    
    $Boo = False
    $file = FileOpen($sFilePath, 0)
    ;MsgBox(0, "$LocRes", "$LocRes+12 =" & $LocRes + 12)
;~     ConsoleWrite("$LocRes+12 =" & $LocRes + 12 & @CRLF)
    _Skip($file, $LocRes + 12)
    $s1 = FileRead($file, 2)  ;-- Read bytes 13,14 to get number of named resource types.
    $iNum1 = Asc($s1)       ;-- number of names.
    ;    ConsoleWrite("$iNum1 =" & $iNum1 & @LF)
    $s2 = FileRead($file, 2)  ;-- Read bytes 15,16 to get number of numbered resource types.
    
    $iNum2 = Asc($s2);-- number of nums.
    ;    ConsoleWrite("$iNum2 =" & $iNum2 & @LF)
    If $iNum2 = 0 Then ;-- no numbered entries. have to quit here.
        Return 3
    EndIf
    
    
    If ($iNum1 > 0) Then _Skip($file, $iNum1 * 8) ;-- Skip past named entries.
    $iReadPt = $LocRes + 16 + ($iNum1 * 8)  ;-- update file offset variable because this will be needed.
    ;ConsoleWrite("$iReadPt ="& $iReadPt&@LF)
    $Boo = False
    For $iOff = 1 To $iNum2
        $s1 = FileRead($file, 8)
        $iReadPt = $iReadPt + 8
        If (Asc($s1) = 16) Then  ;-- this is version info. entry.
            $Boo = True
            ExitLoop
        EndIf
    Next
    If ($Boo = False) Then  ;-- have to quit. no version info. entry found.
        
        ;ConsoleWrite("Return point 1" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
    
    $A1 = _GetArray($s1)  ;-- get a byte array for version info entry at top level.
    ;ConsoleWrite("Ubound>>"&UBound($A1))
    $iOff = 0
    $iNum3 = 1
    ;Do
    While 1
        For $iNum1 = 0 To 2  ;-- get offset number to next level from 2nd 4 bytes of entry structure.
            $A4[$iNum1] = $A1[$iNum1 + 4]
        Next
        $A4[3] = 0
        $iNum2 = _GetNumFromBytes($A4)
        
        If ($A1[7] > 127) Then  ;-- high bit was set in entry offset value, so it;s just a pointer to another pointer.
            $iNum2 = $LocRes + $iNum2 + 16
            _Skip($file, $iNum2 - $iReadPt)   ;- 1)
            $s1 = FileRead($file, 8)
            $iReadPt = $iReadPt + (($iNum2 - $iReadPt) + 8)
            $A1 = _GetArray($s1)
        Else  ;-- this is the offset of version info offset info.!
            $iOff = ($iNum2 + $LocRes)
            ;ExitLoop
            ExitLoop
        EndIf
        $iNum3 = $iNum3 + 1
        If ($iNum3 > 10) Then ExitLoop
    WEnd
    ;Loop
    If ($iOff = 0) Then  ;-- have to quit. no final offset found.
        ;ConsoleWrite("Return point 2" & @LF)
        Return 3  ;failed to find version info in resource table.
        
    EndIf
    _Skip($file, $iOff - $iReadPt)
    $s1 = FileRead($file, 8)
    $iReadPt = $iReadPt + (($iOff - $iReadPt) + 8)
    $A1 = _GetArray($s1)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1]
    Next
    $VIOffset = _GetNumFromBytes($A4)  ;--offset of version info. given in .rsrc section.
    $ReadOffset = (($VIOffset - $VLocRes) + $LocRes)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1 + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4)
    _Skip($file, $ReadOffset - $iReadPt)
    $s1 = FileRead($file, $SizeRes)  ;-- read out the entire FileVersionInfo data area.
    FileClose($file)
    $file = 0
    $sB = _GetByteString($s1, True) ;-- snip unicode.
    $Pt1 = StringInStr($sB, $sVerString)
    If ($Pt1 > 0) Then        ;-- "VS_VER" was found, so process the string and quit.
        $ARet = _ProcessRes($sB)
        $ARet2 = $ARet
        Return 0  ; ok
    ElseIf ($BooAspack = True) Then   ;-- if "VS_VER" was not found but there is an "aspack" section then try that.
        $ReadOffset = (($VIOffset - $VLocAspack) + $LocAspack)  ;-- calculate a new file version info data offset.
        $file = FileOpen($sFilePath, 0)  ;-- The file was closed and is now re-opened here. Keeping the file
        _Skip($file, $ReadOffset)                            ;-- open "just in case" wouldn;t have helped because the file pointer
        $s1 = FileRead($file, $SizeRes)                     ;-- for this read may be further back thean the pointer was when the file
        FileClose($file) ;-- was closed. So rather than try to sort out the read point, the file is just
        $file = 0;-- opened fresh and Skip is used.
        $sB = _GetByteString($s1, True)
        $Pt1 = StringInStr($sB, $sVerString)
        If ($Pt1 > 0) Then
            $ARet = _ProcessRes($sB)
            $ARet2 = $ARet
            Return 0  ; ok
        Else
            ;ConsoleWrite("Return point 3" & @LF)
            Return 3  ;failed to find version info in resource table.
        EndIf
    Else
        ;ConsoleWrite("Return point 4" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
EndFunc   ;==>_GetVersionInfo

Func _ProcessRes($sDat)
    Dim $AInfo[UBound($props) ]
    ;      On Error Resume Next
    For $x = 0 To UBound($props) - 1
        $AInfo[$x] = _GetInfo($sDat, $props[$x])
    Next
    Return $AInfo
EndFunc   ;==>_ProcessRes

Func _GetInfo($sStr, $sVal)
    ; had to rewrite this function because of incompatiblities
    ;between AutoIt3 and Vb string functions.
    Dim $Pta, $Ptb, $LenVal, $s4, $occurance = 1
    $LenVal = StringLen($sVal) + 1  ;-- length of info string: "CompanyName" = 11
    $Pta = StringInStr($sStr, $sVal)  ;-- find string name.
    If ($Pta > 0) Then
        $Pta = $Pta + $LenVal
        $Ptb = $Pta + StringInStr(StringMid($sStr, $Pta + 1), "*")
;~        ConsoleWrite(StringMid($sStr, $Pta + 1) & @LF)
;~        ConsoleWrite(StringMid($sStr, $Pta, ($Ptb - $Pta)) & @LF)
        If $Ptb > ($Pta + 2) Or ($Ptb = ($Pta + 2) And $sVal = "FileVersion") Then              ;-- Name*value**. So start looking at 3rd character after. If that
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))    ;-- character is * then it's Name*** which means there's
            $s4 = StringReplace($s4, "*", "")                                           ;--no value for that specific property.
            If StringInStr($s4, Chr(1), 1) = 0 Then Return $s4   ;-- check for Chr(1) which seems to be found
        EndIf                             ; between values. If it's in the string that means there is no value for
        
    EndIf
    Return ""
EndFunc   ;==>_GetInfo
;-------------- simplified version of _GetByteString For this Class. ---------------------
Func _GetByteString($sStr, $SnipUnicode)
    Local $sRet, $iLen, $iA, $iLen2, $A2[2]
    ;    On Error Resume Next
    $iLen2 = 0
    If ($SnipUnicode = False) Then
        ReDim $A2[StringLen($sStr) ]
        For $iLen = 1 To StringLen($sStr)
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            ;If UBound($A2) > $iLen - 1 Then
            $A2[$iLen - 1] = Chr($iA)
        Next
    Else
        ReDim $A2[ (StringLen($sStr) / 2) ]
        For $iLen = 1 To StringLen($sStr) Step 2
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            $A2[$iLen2] = Chr($iA)
            $iLen2 = $iLen2 + 1
        Next
    EndIf
    Return _Join($A2, "")
EndFunc   ;==>_GetByteString
;-------------------------------- Simplified version of _GetArray. -----------------------
Func _GetArray($sStr)
    Dim $iA, $Len1, $Len2, $AStr[2]
    ;  On Error Resume Next
    $Len1 = StringLen($sStr)
    If $Len1 > 1 Then ReDim $AStr[ ($Len1) ]
    For $iA = 1 To $Len1
        $AStr[$iA - 1] = Asc(StringMid($sStr, $iA, 1))
    Next
    Return $AStr
EndFunc   ;==>_GetArray
;-------------------- return a number from 2 or 4 bytes. ---------------
Func _GetNumFromBytes($ABytes)
    Dim $Num1
    ;    Err.Clear
    ;        On Error Resume Next
    ;_GetNumFromBytes = -1
    If UBound($ABytes) > 1 Then
        $Num1 = ($ABytes[0] + $ABytes[1] * 256)
        If (UBound($ABytes) > 3) Then
            $Num1 = $Num1 + ($ABytes[2] * 65536) + ($ABytes[3] * 16777216)
        EndIf
        Return $Num1
    EndIf
EndFunc   ;==>_GetNumFromBytes

Func _Join($aStrJ, $sDelim = "")
    ;mimic VB Join command (array to string with delimiter)
    Local $sTemp
    If IsArray($aStrJ) Then
        For $x = 0 To UBound($aStrJ) - 1
            $sTemp = $sTemp & $aStrJ[$x] & $sDelim
        Next
        ;ConsoleWrite("Join $sTemp =" & $sTemp & @LF)
        Return $sTemp
    EndIf
    SetError(1)
    Return ""
EndFunc   ;==>_Join

Func _Skip($hfile, $bytes)
    ;mimic FSO.skip
    Local $temp = FileRead($hfile, $bytes)
    If @error Then Return 0
    Return 1
EndFunc   ;==>_Skip

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Link to comment
Share on other sites

no need to change code with this one, if you want more that the basic information pass the information in wanted, i.e.

"Windows2000-KB914388-x86-ENU.EXE" "CompanyName" "FileDescription" "FileVersion" "ProductName" "LegalCopyright" "OriginalFilename" "Installer Engine" "Applies to" "Build Date"
oÝ÷ Ù«­¢+Ø(ì´´Q¡¥ÌÍÉ¥ÁÐ¥¹±Õ̱Í̹µ¼¸É½À¹äA¥±½¹Ñ¼Ñ¡ÍÉ¥ÁСa°10°=(촴ѼХ±ÁɽÁÉѥ̸Q¡±ÍÌ°
±ÍAɽÁÌ°¥Ì½µÁ±ÑÍн±°Õ¹Ñ¥½¹Ì¹(ì´´Ð¥±ÁɽÁÉÑ¥ÌÕÍ¥¹½¹±äY   L¹Ñ¡QáÑÍÑÉ´½©Ð¸(ì´´Q¡¥±ÁɽÁÉÑ¥ÌÉÑÕɹÉÑ¡½ÍÑ¡Ðɽչݡ¸¥±¥ÌÉ¥¡Ðµ±¥­°(ì´´AɽÁÉѥ̵¹Ô¥Ì±¥­°¹YÉÍ¥½¸Ñ¥ÌͱѸQ¡¥Ì¥¹½ÉµÑ¥½¸(ì´´¥Ì¥¹±Õ¥¸µ½ÍÐA¡Á½ÉѱáÕѱ¤¥±Ì¸((ì´´Q¡¹¬å½ÔѼÉÕɵ¸¡¡ÑÑÀè¼½ÝÝܹɩյÀ¹½´¤½È¡±ÀÝ¥Ñ Ñ¡¥Ì½¸(ì´´!½ÉÉÑÕ¹±Í¼Ý½É­½ÕÐÑ¡ÅÕ½ÐíÍÁ¬ÅÕ½ÐìÙɥѥ½¸Ý¡Éäͽµ(ì´´A¥±Ì¡Ù¸½µÁÉÍ͹ÉÅեɥɹеѡ½Ñ¼¥¹Ñ¡ÙÉÍ¥½¸¥¹¼¸¨¸((ì´´9=QèQ¡¥ÌÍÉ¥ÁÐ¥ÌÝÉ¥ÑѸѼ½µÁнÈÁÍÑ¥¹¥¹Ñ¼ÍÉ¥ÁÑ̸%ÐÕÍÌÍ¥µÁ±¥¥ÙÉÍ¥½¹Ì½Í½µÕ¹Ñ¥½¹Ìɽ´(ì´´Ñ¡QáÑÍÑÉ´   ¥¹Éä=Á̹ ÍØнݹ±½°ÕÍ¥¹½¹±äѡչѥ½¹±¥Ñä¹Ñ¼Ð¥±ÙÉÍ¥½¸¥¹¼¸°(ì´´¥¸½ÉÈѼ­ÀÑ¡¥Ì±ÍÌÌ͵±°ÌÁ½ÍÍ¥±¸%å½ÔݹÐѼÕÍչѥ½¹ÌÍÕ Ì}ÑÉÉä½È}Ñ åÑMÑÉ¥¹(ì´´å½ÔµäݹÐѼ½Ý¹±½Ñ¡½Ñ¡ÈÁ­¸%ÐÁɽ٥̥ɱ併Á±ÑÍнµÑ¡½Ì½Èݽɭ¥¹Ý¥Ñ ¥¹É䥱̸((ì´´µ¼ÍÉ¥Áд´´´´´´´´´´´´´´´´´´´(í
½¹ÙÉÑѼÕѽ%ÑXÌMÑÙA½¡©­¤m±Ñ½ÉɽtÍÑÙ½½Ñ¥±±¼¹ÍåÑ̹¹Ð((íø±½°ÀÌØíÁɽÁÍlÄátôlÅÕ½Ðí
½µÁ¹å9µÅÕ½Ðì°ÅÕ½Ðí¥±ÍÉ¥ÁÑ¥½¸ÅÕ½Ðì°ÅÕ½Ðí¥±YÉÍ¥½¸ÅÕ½Ðì°ÅÕ½ÐíAɽÕÑ9µÅÕ½Ðì°ÅÕ½Ðí1±
½ÁåÉ¥¡ÐÅÕ½Ðì°|(íø$$ÅÕ½Ðí=É¥¥¹±¥±¹µÅÕ½Ðì°ÅÕ½Ðí%¹Íѱ±È¹¥¹ÅÕ½Ðì°ÅÕ½ÐíÁÁ±¥ÌѼÅÕ½Ðì°ÅÕ½Ðí  Õ¥±ÑÅÕ½Ðì°ÅÕ½Ðí%¹Íѱ±Ñ¥½¸QåÁÅÕ½Ðì°|(íø$$ÅÕ½Ðí%¹Íѱ±ÈYÉÍ¥½¸ÅÕ½Ðì°ÅÕ½Ðí%¹Ñɹ±9µÅÕ½Ðì°ÅÕ½Ðí-ÉÑ¥±9ÕµÈÅÕ½Ðì°ÅÕ½ÐíMÕÁÁ½ÉÐ1¥¹¬ÅÕ½Ðì°ÅÕ½ÐíA­QåÁÅÕ½Ðì°|(íø$$ÅÕ½ÐíAɽ¸É¡¥ÑÑÕÉÅÕ½Ðì°ÅÕ½ÐíM±µáÑÉѽÈYÉÍ¥½¸ÅÕ½Ðì°ÅÕ½Ðí¥ÍÁ±å9µÅÕ½Ðít(íM=¹Õѽ%ÑMÑÉÐ ¤(ìÀÌØíÉôÅÕ½Ðí]¥¹½ÝÌÈÀÀÀµ-äÄÐÌààµààص9T¹aÅÕ½Ðì(ìÀÌØíÉôÅÕ½Ðíé]%9=]MMeMQ4Ìɵ¡É¹±°ÅÕ½Ðì(ìÀÌØíÉôÅÕ½Ðíé]%9=]MMeMQ4ÌÉi±¥Q½½°¹½àÅÕ½Ðì(ìÀÌØíÉôÅÕ½Ðíé]%9=]MMeMQ4ÌÉ
±¹áÅÕ½Ðì(ìÀÌØíÉôÅÕ½Ðí]¥¹½ÝÌÈÀÀÀµ-äÄÐÌààµààص9T¹aÅÕ½ÐìÅÕ½Ðí
½µÁ¹å9µÅÕ½ÐìÅÕ½Ðí¥±ÍÉ¥ÁÑ¥½¸ÅÕ½ÐìÅÕ½Ðí¥±YÉÍ¥½¸ÅÕ½ÐìÅÕ½ÐíAɽÕÑ9µÅÕ½ÐìÅÕ½Ðí1±
½ÁåÉ¥¡ÐÅÕ½ÐìÅÕ½Ðí=É¥¥¹±¥±¹µÅÕ½ÐìÅÕ½Ðí%¹Íѱ±È¹¥¹ÅÕ½Ðì((ì´´¹µ¼ÍÉ¥Áд´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´((ì´´¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼MÑÉÐ
±ÍÌè
±ÍAɽÁ̼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼(ì(ìչѥ½¹Ì¥¸Ñ¡¥Ì±Í̸¡±°Õ¹Ñ¥½¹Ìɹ½ÈÑÑ¥¹¥±ÙÉÍ¥½¸¥¹½ÉµÑ¥½¸¸¤(ì(ìAÕ±¥Õ¹Ñ¥½¸}ÑYÉÍ¥½¹%¹¼ ÀÌØíÍ¥±AÑ °ÀÌØíIÐȤ´ÉÑÕɹÌÙÉÍ¥½¸¥¹½ÉµÑ¥½¸½ÈA¥±Ì¸(ì=¸ÍÕÍÌÀÌØíIÐÈÉÑÕɹÌÉÉä Ô¤½¹Ñ¥¹¥¹ÙÉÍ¥½¸¥¹¼¸ÍÑÉ¥¹Ì½È¥±¸(ìչѥ½¸ÉÑÕɸÉɽȽÌèÀôÍÕÍ̸Äô¥¹Ù±¥¥±ÁÑ ¸Èô¹¼¹ÉÍÉѱ±¥ÍÑ¥¸ÍÑ¥½¸Ñ±¸(ìÌô¥±Ñ¼¥¹ÙÉÍ¥½¸¥¹¼¸Ðô¹½ÐA¥±¸Ôô¥±¥ÌÄص¥ÐáÕѱ¸ ÅÕ½Ðí9ÅÕ½Ð쥱ÉÑ¡ÈÑ¡¸ÅÕ½ÐíAÅÕ½Ðì¤(ì(ìAÉ¥ÙÑ¡¥¹Ñɹ°¤Õ¹Ñ¥½¹Ìè(ì}ÑÉÉä¡MÑÉ¥¹%¸¤´½¹ÙÉÐÍÑÉ¥¹Ñ¼¸ÉÉä½åÑÙ±Õ̸(ì}Ñ    åÑMÑÉ¥¹¡MÑÉ¥¹%¸°ÀÌØíM¹¥ÁU¹¥½¤´½¹ÙÉÐÍÑÉ¥¹Ñ¼µ¹±ÙÉÍ¥½¸¸%ÀÌØíM¹¥ÁU¹¥½ôQÉÕÑ¡¸Ð½¹±äÙÉäɹåѸ(ì}Ñ9յɽµ  åÑÌ¡ÉÉ䤴ѭÌÉÉä½Õ½Õ¹Ä½È̸ÉÑÕɸ¹ÕµÉ¥Ù±Õ½ÈȽÈÐåÑ̸(ì(ì(ì(ì(ì(ì´´´´´´´´´´´´´´´´¼¼¼¼¼¼¼¼¼¼¼¼´´´    %8
±ÍÌ!I´´´¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼¼´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´()Õ¹=¹Õѽ%ÑMÑÉÐ ¤($íÕ¹½µµ¹ÐÑ¡¥Ì½ÈÉѼ½È½µµ¹±¥¹Õ͸(%%ÀÌØí
µ1¥¹lÁtôÀQ¡¸($%5Í  ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÅÕ½ÐíɽÀA¥±maµ10µ=
at½¹Ñ¼Ñ¡¥ÌÍÉ¥ÁÐѼÐÙÉÍ¥½¸¥¹½ÉµÑ¥½¸¸ÅÕ½ÐìµÀì|($$$%
I1µÀìÅÕ½Ðí
½µµAɽµÁÐUÍèÅÕ½ÐìµÀì
I1µÀìMÉ¥ÁÑ9µµÀìÅÕ½ÐìÅÕ½ÐìµÀìÅÕ½Ðíµå¥±¹má±±°±½átÅÕ½Ðì¤($%á¥Ð(%¹%(%±½°ÀÌØíÉôÀÌØí
µ1¥¹lÅt(%±½°ÀÌØíÁɽÁÍlÙtôlÅÕ½Ðí
½µÁ¹å9µÅÕ½Ðì°ÅÕ½Ðí¥±ÍÉ¥ÁÑ¥½¸ÅÕ½Ðì°ÅÕ½Ðí¥±YÉÍ¥½¸ÅÕ½Ðì°ÅÕ½ÐíAɽÕÑ9µÅÕ½Ðì°ÅÕ½Ðí1±
½ÁåÉ¥¡ÐÅÕ½Ðì°|($$$ÅÕ½Ðí=É¥¥¹±¥±¹µÅÕ½Ðít(%%ÀÌØí
µ1¥¹lÁtÐìÄQ¡¸($%I¥´ÀÌØíÁɽÁÍlÀÌØí
µ1¥¹lÁt´Åt($%½ÈÀÌØíàôÈQ¼ÀÌØí
µ1¥¹lÁt($$%%ÀÌØíàÐìÄQ¡¸ÀÌØíÁɽÁÍlÀÌØíà´ÉtôÀÌØí
µ1¥¹lÀÌØíát($%9áÐ(%¹%(%}5¥¸ ¤)¹Õ¹ìôôÐí=¹Õѽ%ÑMÑÉÐ()Õ¹}5¥¸ ¤(%±½°ÀÌØíÍÍаÀÌØí9ÕµÌ(%±½°ÀÌØíÉ°ÀÌØí¤È°ÀÌØíIÑÕɸ°ÀÌØíÌ($($ÀÌØí¤Èô}ÑYÉÍ¥½¹%¹¼ ÀÌØíÉ°ÀÌØíIÑÕɸ¤(%MÝ¥Ñ ÀÌØí¤È($%
ÍÄ($$%5Í ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÅÕ½Ðí¥±ÁÑ ¹½ÐÙ±¥ÅÕ½Ðì¤($%
ÍÈ($$%5Í ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÅÕ½ÐíU¹±Ñ¼¥¹IͽÕÉѱ¡È¥¸¥±¸ÅÕ½Ðì¤($%
ÍÌ($$%5Í ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÅÕ½ÐíU¹±Ñ¼¥¹¥±ÙÉÍ¥½¸¥¹¼¸¥¸¥±¸ÅÕ½Ðì¤($%
ÍÐ($$%5Í ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÅÕ½ÐíQ¡¥Ì¥Ì¹½ÐA¥±¸ÅÕ½Ðì¤($%
ÍÔ($$%5Í ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÅÕ½ÐíQ¡¥Ì¥ÌÄص¥ÐáÕѱ¸%Х̹½ÐA¥±¸ÅÕ½Ðì¤($%
ÍÀìÍÕÍÌ($$$ÀÌØíÌôÅÕ½ÐìÅÕ½Ðì($$%½ÈÀÌØíàôÀQ¼U    ½Õ¹ ÀÌØíÁɽÁ̤´Ä($$$$ÀÌØí̵ÀìôÀÌØíÁɽÁÍlÀÌØíátµÀìÅÕ½ÐìèÅÕ½ÐìµÀìÀÌØíIÑÕɹlÀÌØíátµÀì
I1($$%9áÐ($$%5Í  ½à ÈØØÈàà°MÉ¥ÁÑ9µ°ÀÌØíɵÀì
I1µÀì
I1µÀìÀÌØí̤(%¹MÝ¥Ñ )¹Õ¹ìôôÐí}5¥¸(((ì´´Q¡ÁÕ±¥Õ¹Ñ¥½¸¥¸Ñ¡¥Ì±ÍÌè}ÑYÉÍ¥½¹%¹¼´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´)Õ¹}ÑYÉÍ¥½¹%¹¼ ÀÌØíÍ¥±AÑ °   åIÀÌØíIÐȤ촴ÉÑÕɸÉÉä Ô¤(%1½°ÀÌØíIаÀÌØíÌÄ°ÀÌØíÍ°ÀÌØíAÐÄ°ÀÌØíÍIÌ°ÀÌØíÄ°ÀÌØíÑlÑt°ÀÌØíÉlÑt°ÀÌØí1½IÌ°ÀÌØíY1½IÌ°ÀÌØíM¥éIÌ°ÀÌØí¥=°ÀÌØí   ½¼°ÀÌØíÍYÉMÑÉ¥¹°ÀÌØíÍ5É­È(%1½°ÀÌØí¥9Õ´Ä°ÀÌØí¥9Õ´È°ÀÌØí¥IAаÀÌØí¥9Õ´Ì°ÀÌØí1½ÍÁ¬°ÀÌØíY1½ÍÁ¬°ÀÌØíY%=ÍаÀÌØíI=ÍаÀÌØí ½½ÍÁ¬($ì=¸ÉɽÈIÍÕµ9áÐ(%%9½Ð¥±á¥ÍÑÌ ÀÌØíÍ¥±AÑ ¤Q¡¸($%IÑÕɸÄíÁÑ ¸(%¹%($ÀÌØíÍIÌôÅÕ½Ðì¹ÉÍÉÅÕ½Ðì($ÀÌØíÍYÉMÑÉ¥¹ôÅÕ½ÐíYM}YHÅÕ½Ðì($ÀÌØí ½½ÍÁ¬ô±Í($($($ÀÌØí¥±ô¥±=Á¸ ÀÌØíÍ¥±AÑ °À¤($ÀÌØíÌÄô¥±I ÀÌØíÍ¥±AÑ °ÈÀÐà¤(%¥±
±½Í ÀÌØí¥±¤($ÀÌØí¥±ôÀ($í
½¹Í½±]É¥Ñ ÀÌØíÌĤ($ÀÌØíÄô}ÑÉÉä¡MÑÉ¥¹5¥ ÀÌØíÌÄ°ØİȤ¤ì´´Ð¹ÕµÈÙ±ÕнÍÐØÀÑ¡ÐÁ½¥¹ÑÌѼAÍ¥¹ÑÕÉÉÍ̸($($ÀÌØí¥9Õ´Äô¡}Ñ9յɽµ    åÑÌ ÀÌØíĤ¬Ä¤ì´´Ð½ÍнÅÕ½ÐíAÀÀÅÕ½Ðì($ÀÌØíÍô}Ñ åÑMÑÉ¥¹ ÀÌØíÌÄ°±Í¤ì´´Ðݽɭ±ÍÑÉ¥¹Ý¥Ñ 
¡È À¤ÉÁ±äÅÕ½Ðì¨ÅÕ½Ðì¸($ÀÌØíÍ5É­ÈôMÑÉ¥¹5¥ ÀÌØíÍ°ÀÌØí¥9մİФ(íø%
½¹Í½±]É¥Ñ ÅÕ½ÐìÀÌØíÍ5É­ÈôÅÕ½ÐìµÀìÀÌØíÍ5ɭȵÀí1¤(%% ÀÌØíÍ5ɭȱÐìÐìÅÕ½ÐíA¨¨ÅÕ½Ðì¤Q¡¸($%%MÑÉ¥¹1Ð ÀÌØíÍ5ɭȰȤôÅÕ½Ðí9ÅÕ½ÐìQ¡¸($$%IÑÕɸÔì´´Äإи($%±Í($$%IÑÕɸÐì´´¹¼AÍ¥¹ÑÕɽչ¸($%¹%(%¹%($($ÀÌØíAÐÄôMÑÉ¥¹%¹MÑÈ ÀÌØíÍ°ÀÌØíÍI̤촴¥¹¹ÉÍÉѱ¸(%% ÀÌØíAÐÄôÀ¤Q¡¸($%IÑÕɸÈí¹¼ÉͽÕÉѱ¡È½Õ¹¸(%¹%($ÀÌØíAÐÄôÀÌØíAÐĬÄÈì´´Í¥é½ÉÜÑ¥ÌÐåÑÌнÍнÄØ¥¹Ñ¼Ñ¡¹ÉÍÉѱ¸($ÀÌØíÄô}ÑÉÉä¡MÑÉ¥¹5¥ ÀÌØíÌÄ°ÀÌØíAÐÄ°ÄȤ¤ì´´Ðѡ͵ÍÑÉ¥¹Ì¹ÕµÉ¥ÉÉäѼI½ÍйյÉ̸(%½ÈÀÌØí¥=ôÀQ¼Ì($$í
½¹Í½±]É¥Ñ ÅÕ½ÐìÀÌØí¥=ôÅÕ½ÐìµÀìÀÌØí¥=µÀí1¤($$ÀÌØíÑlÀÌØí¥=tôÀÌØíÅlÀÌØí¥=t(%9áÐ($ÀÌØíY1½IÌô}Ñ9յɽµ    åÑÌ ÀÌØíФ(%½ÈÀÌØí¥=ôÀQ¼Ì($$ÀÌØíÑlÀÌØí¥=tôÀÌØíÅlÀÌØí¥=¬Ñt(%9áÐ($ÀÌØíM¥éIÌô}Ñ9յɽµ   åÑÌ ÀÌØíФ촵ͥé½ÉͽÕÉÍÑ¥½¸¥¸åÑ̸(%½ÈÀÌØí¥=ôÀQ¼Ì($$ÀÌØíÑlÀÌØí¥=tôÀÌØíÅlÀÌØí¥=¬át(%9áÐ($ÀÌØí1½IÌô}Ñ9յɽµ   åÑÌ ÀÌØíФ촴½Íб½Ñ¥½¸½ÉͽÕÉÍÑ¥½¸¸($ÀÌØíAÐÄôMÑÉ¥¹%¹MÑÈ Ä°ÀÌØíÍ°ÅÕ½Ðì¹ÍÁ¬ÅÕ½Ðì¤ì´´¥¹¹ÉÍÉѱ¸(%% ÀÌØíAÐÄÐìÀ¤Q¡¸($$ÀÌØí   ½½ÍÁ¬ôQÉÕ($$ÀÌØíAÐÄôÀÌØíAÐĬÄÈì´´Ù¥ÉÑÕ°½ÍХ̥ÉÍÐÐåÑÌìÉܽÍÐ¥ÌåÑÌä´Äȸ($$ÀÌØíÄô}ÑÉÉä¡MÑÉ¥¹5¥ ÀÌØíÌÄ°ÀÌØíAÐÄ°ÄȤ¤($%½ÈÀÌØí¥=ôÀQ¼Ì($$$ÀÌØíÑlÀÌØí¥=tôÀÌØíÅlÀÌØí¥=t($%9áÐ($$ÀÌØíY1½ÍÁ¬ô}Ñ9յɽµ  åÑÌ ÀÌØíФ($%½ÈÀÌØí¥=ôÀQ¼Ì($$$ÀÌØíÑlÀÌØí¥=tôÀÌØíÅlÀÌØí¥=¬át($%9áÐ($$ÀÌØí1½ÍÁ¬ô}Ñ9յɽµ  åÑÌ ÀÌØíФ(%¹%($($ÀÌØí    ½¼ô±Í($ÀÌØí¥±ô¥±=Á¸ ÀÌØíÍ¥±AÑ °À¤($í5Í ½à À°ÅÕ½ÐìÀÌØí1½IÌÅÕ½Ðì°ÅÕ½ÐìÀÌØí1½I̬ÄÈôÅÕ½ÐìµÀìÀÌØí1½I̬ÄȤ(íø
½¹Í½±]É¥Ñ ÅÕ½ÐìÀÌØí1½I̬ÄÈôÅÕ½ÐìµÀìÀÌØí1½I̬ÄȵÀì
I1¤(%}M­¥À ÀÌØí¥±°ÀÌØí1½I̬ÄȤ($ÀÌØíÌÄô¥±I ÀÌØí¥±°È¤ì´´IåÑÌÄÌ°ÄÐѼйյȽ¹µÉͽÕÉÑåÁ̸($ÀÌØí¥9Õ´ÄôÍ ÀÌØíÌĤ촴¹ÕµÈ½¹µÌ¸($ì
½¹Í½±]É¥Ñ ÅÕ½ÐìÀÌØí¥9Õ´ÄôÅÕ½ÐìµÀìÀÌØí¥9մĵÀì1¤($ÀÌØíÌÈô¥±I ÀÌØí¥±°È¤ì´´IåÑÌÄÔ°ÄØѼйյȽ¹ÕµÉÉͽÕÉÑåÁ̸($($ÀÌØí¥9Õ´ÈôÍ ÀÌØíÌȤ촴¹ÕµÈ½¹ÕµÌ¸($ì
½¹Í½±]É¥Ñ ÅÕ½ÐìÀÌØí¥9Õ´ÈôÅÕ½ÐìµÀìÀÌØí¥9մȵÀì1¤(%%ÀÌØí¥9Õ´ÈôÀQ¡¸ì´´¹¼¹ÕµÉ¹Ñɥ̸¡ÙѼÅեСɸ($%IÑÕɸÌ(%¹%($($(%% ÀÌØí¥9Õ´ÄÐìÀ¤Q¡¸}M­¥À ÀÌØí¥±°ÀÌØí¥9մĨà¤ì´´M­¥ÀÁÍйµ¹Ñɥ̸($ÀÌØí¥IAÐôÀÌØí1½I̬Äج ÀÌØí¥9մĨà¤ì´´ÕÁÑ¥±½ÍÐÙÉ¥±ÕÍÑ¡¥ÌÝ¥±°¹¸($í
½¹Í½±]É¥Ñ ÅÕ½ÐìÀÌØí¥IAÐôÅÕ½ÐìµÀìÀÌØí¥IAеÀí1¤($ÀÌØí   ½¼ô±Í(%½ÈÀÌØí¥=ôÄQ¼ÀÌØí¥9Õ´È($$ÀÌØíÌÄô¥±I ÀÌØí¥±°à¤($$ÀÌØí¥IAÐôÀÌØí¥IAЬà($%%¡Í ÀÌØíÌĤôÄؤQ¡¸ì´´Ñ¡¥Ì¥ÌÙÉÍ¥½¸¥¹¼¸¹ÑÉä¸($$$ÀÌØí   ½¼ôQÉÕ($$%á¥Ñ1½½À($%¹%(%9áÐ(%% ÀÌØí   ½¼ô±Í¤Q¡¸ì´´¡ÙѼÅեи¹¼ÙÉÍ¥½¸¥¹¼¸¹ÑÉä½Õ¹¸($$($$í
½¹Í½±]É¥Ñ ÅÕ½ÐíIÑÕɸÁ½¥¹ÐÄÅÕ½ÐìµÀì1¤($%IÑÕɸÌí¥±Ñ¼¥¹ÙÉÍ¥½¸¥¹¼¥¸ÉͽÕÉѱ¸(%¹%($($ÀÌØíÄô}ÑÉÉä ÀÌØíÌĤ촴ÐåÑÉÉä½ÈÙÉÍ¥½¸¥¹¼¹ÑÉäÐѽÀ±Ù°¸($í
½¹Í½±]É¥Ñ ÅÕ½ÐíU½Õ¹ÐìÐìÅÕ½ÐìµÀíU    ½Õ¹ ÀÌØíĤ¤($ÀÌØí¥=ôÀ($ÀÌØí¥9Õ´ÌôÄ($í¼(%]¡¥±Ä($%½ÈÀÌØí¥9Õ´ÄôÀQ¼È촴нÍйյÈѼ¹áбٰɽ´É¹ÐåÑ̽¹ÑÉäÍÑÉÕÑÕɸ($$$ÀÌØíÑlÀÌØí¥9Õ´ÅtôÀÌØíÅlÀÌØí¥9մĬÑt($%9áÐ($$ÀÌØíÑlÍtôÀ($$ÀÌØí¥9Õ´Èô}Ñ9յɽµ  åÑÌ ÀÌØíФ($$($%% ÀÌØíÅlÝtÐìÄÈܤQ¡¸ì´´¡¥ ¥ÐÝÌÍÐ¥¸¹ÑÉä½ÍÐٱհͼ¥ÐíÌ©ÕÍÐÁ½¥¹ÑÈѼ¹½Ñ¡ÈÁ½¥¹Ñȸ($$$ÀÌØí¥9Õ´ÈôÀÌØí1½I̬ÀÌØí¥9մȬÄØ($$%}M­¥À ÀÌØí¥±°ÀÌØí¥9Õ´È´ÀÌØí¥IAФì´Ä¤($$$ÀÌØíÌÄô¥±I ÀÌØí¥±°à¤($$$ÀÌØí¥IAÐôÀÌØí¥IAЬ  ÀÌØí¥9Õ´È´ÀÌØí¥IAФ¬à¤($$$ÀÌØíÄô}ÑÉÉä ÀÌØíÌĤ($%±Íì´´Ñ¡¥Ì¥ÌÑ¡½ÍнÙÉÍ¥½¸¥¹¼½ÍÐ¥¹¼¸ÌÌì($$$ÀÌØí¥=ô ÀÌØí¥9մȬÀÌØí1½I̤($$$íá¥Ñ1½½À($$%á¥Ñ1½½À($%¹%($$ÀÌØí¥9Õ´ÌôÀÌØí¥9մ̬Ä($%% ÀÌØí¥9Õ´ÌÐìÄÀ¤Q¡¸á¥Ñ1½½À(%]¹($í1½½À(%% ÀÌØí¥=ôÀ¤Q¡¸ì´´¡ÙѼÅեи¹¼¥¹°½Íнչ¸($$í
½¹Í½±]É¥Ñ ÅÕ½ÐíIÑÕɸÁ½¥¹ÐÈÅÕ½ÐìµÀì1¤($%IÑÕɸÌí¥±Ñ¼¥¹ÙÉÍ¥½¸¥¹¼¥¸ÉͽÕÉѱ¸($$(%¹%(%}M­¥À ÀÌØí¥±°ÀÌØí¥=´ÀÌØí¥IAФ($ÀÌØíÌÄô¥±I ÀÌØí¥±°à¤($ÀÌØí¥IAÐôÀÌØí¥IAЬ  ÀÌØí¥=´ÀÌØí¥IAФ¬à¤($ÀÌØíÄô}ÑÉÉä ÀÌØíÌĤ(%½ÈÀÌØí¥9Õ´ÄôÀQ¼Ì($$ÀÌØíÑlÀÌØí¥9Õ´ÅtôÀÌØíÅlÀÌØí¥9Õ´Åt(%9áÐ($ÀÌØíY%=ÍÐô}Ñ9յɽµ    åÑÌ ÀÌØíФ촵½ÍнÙÉÍ¥½¸¥¹¼¸¥Ù¸¥¸¹ÉÍÉÍÑ¥½¸¸($ÀÌØíI=ÍÐô  ÀÌØíY%=ÍдÀÌØíY1½I̤¬ÀÌØí1½I̤(%½ÈÀÌØí¥9Õ´ÄôÀQ¼Ì($$ÀÌØíÑlÀÌØí¥9Õ´ÅtôÀÌØíÅlÀÌØí¥9մĬÑt(%9áÐ($ÀÌØíM¥éIÌô}Ñ9յɽµ åÑÌ ÀÌØíФ(%}M­¥À ÀÌØí¥±°ÀÌØíI=ÍдÀÌØí¥IAФ($ÀÌØíÌÄô¥±I ÀÌØí¥±°ÀÌØíM¥éI̤촴ɽÕÐÑ¡¹Ñ¥É¥±YÉÍ¥½¹%¹¼Ñɸ(%¥±
±½Í ÀÌØí¥±¤($ÀÌØí¥±ôÀ($ÀÌØíÍô}Ñ    åÑMÑÉ¥¹ ÀÌØíÌÄ°QÉդ촴͹¥ÀÕ¹¥½¸($ÀÌØíAÐÄôMÑÉ¥¹%¹MÑÈ ÀÌØíÍ°ÀÌØíÍYÉMÑÉ¥¹¤(%% ÀÌØíAÐÄÐìÀ¤Q¡¸ì´´ÅÕ½ÐíYM}YHÅÕ½ÐìÝ̽չ°Í¼ÁɽÍÌÑ¡ÍÑÉ¥¹¹Åեи($$ÀÌØíIÐô}AɽÍÍIÌ ÀÌØíͤ($$ÀÌØíIÐÈôÀÌØíIÐ($%IÑÕɸÀ콬(%±Í% ÀÌØí  ½½ÍÁ¬ôQÉÕ¤Q¡¸ì´´¥ÅÕ½ÐíYM}YHÅÕ½ÐìÝ̹½Ð½Õ¹ÕÐѡɥ̸ÅÕ½ÐíÍÁ¬ÅÕ½ÐìÍÑ¥½¸Ñ¡¸ÑÉäѡи($$ÀÌØíI=ÍÐô  ÀÌØíY%=ÍдÀÌØíY1½ÍÁ¬¤¬ÀÌØí1½ÍÁ¬¤ì´´±Õ±Ñ¹Ü¥±ÙÉÍ¥½¸¥¹¼Ñ½Íи($$ÀÌØí¥±ô¥±=Á¸ ÀÌØíÍ¥±AÑ °À¤ì´´Q¡¥±Ý̱½Í¹¥Ì¹½Üɵ½Á¹¡É¸-Á¥¹Ñ¡¥±($%}M­¥À ÀÌØí¥±°ÀÌØíI=ÍФ촴½Á¸ÅÕ½Ðí©ÕÍÐ¥¸ÍÅÕ½Ðìݽձ¸íС١±ÁÕÍÑ¡¥±Á½¥¹ÑÈ($$ÀÌØíÌÄô¥±I ÀÌØí¥±°ÀÌØíM¥éI̤촴½ÈÑ¡¥ÌɵäÕÉѡȬѡ¸Ñ¡Á½¥¹ÑÈÝÌÝ¡¸Ñ¡¥±($%¥±
±½Í ÀÌØí¥±¤ì´´Ý̱½Í¸M¼ÉÑ¡ÈÑ¡¸ÑÉäѼͽÉнÕÐÑ¡ÉÁ½¥¹Ð°Ñ¡¥±¥Ì©ÕÍÐ($$ÀÌØí¥±ôÀì´´½Á¹ÉÍ ¹M­¥À¥ÌÕ͸($$ÀÌØíÍô}Ñ åÑMÑÉ¥¹ ÀÌØíÌÄ°QÉÕ¤($$ÀÌØíAÐÄôMÑÉ¥¹%¹MÑÈ ÀÌØíÍ°ÀÌØíÍYÉMÑÉ¥¹¤($%% ÀÌØíAÐÄÐìÀ¤Q¡¸($$$ÀÌØíIÐô}AɽÍÍIÌ ÀÌØíͤ($$$ÀÌØíIÐÈôÀÌØíIÐ($$%IÑÕɸÀ콬($%±Í($$$í
½¹Í½±]É¥Ñ ÅÕ½ÐíIÑÕɸÁ½¥¹ÐÌÅÕ½ÐìµÀì1¤($$%IÑÕɸÌí¥±Ñ¼¥¹ÙÉÍ¥½¸¥¹¼¥¸ÉͽÕÉѱ¸($%¹%(%±Í($$í
½¹Í½±]É¥Ñ ÅÕ½ÐíIÑÕɸÁ½¥¹ÐÐÅÕ½ÐìµÀì1¤($%IÑÕɸÌí¥±Ñ¼¥¹ÙÉÍ¥½¸¥¹¼¥¸ÉͽÕÉѱ¸(%¹%)¹Õ¹ìôôÐí}ÑYÉÍ¥½¹%¹¼()Õ¹}AɽÍÍIÌ ÀÌØíÍФ(%¥´ÀÌØí%¹½mU  ½Õ¹ ÀÌØíÁɽÁ̤t($ì=¸ÉɽÈIÍÕµ9áÐ(%½ÈÀÌØíàôÀQ¼U ½Õ¹ ÀÌØíÁɽÁ̤´Ä($$ÀÌØí%¹½lÀÌØíátô}Ñ%¹¼ ÀÌØíÍаÀÌØíÁɽÁÍlÀÌØíát¤(%9áÐ(%IÑÕɸÀÌØí%¹¼)¹Õ¹ìôôÐí}AɽÍÍIÌ()Õ¹}Ñ%¹¼ ÀÌØíÍMÑÈ°ÀÌØíÍY°¤($ì¡Ñ¼ÉÝÉ¥ÑÑ¡¥Ìչѥ½¸Õͽ¥¹½µÁÑ¥±¥Ñ¥Ì($íÑݸÕѽ%Ð̹YÍÑÉ¥¹Õ¹Ñ¥½¹Ì¸(%¥´ÀÌØíAÑ°ÀÌØíAÑ°ÀÌØí1¹Y°°ÀÌØíÌаÀÌØí½ÕɹôÄ($ÀÌØí1¹Y°ôMÑÉ¥¹1¸ ÀÌØíÍY°¤¬Äì´´±¹Ñ ½¥¹¼ÍÑÉ¥¹èÅÕ½Ðí
½µÁ¹å9µÅÕ½ÐìôÄÄ($ÀÌØíAÑôMÑÉ¥¹%¹MÑÈ ÀÌØíÍMÑÈ°ÀÌØíÍY°¤ì´´¥¹ÍÑÉ¥¹¹µ¸(%% ÀÌØíAÑÐìÀ¤Q¡¸($$ÀÌØíAÑôÀÌØíAѬÀÌØí1¹Y°($$ÀÌØíAÑôÀÌØíAѬMÑÉ¥¹%¹MÑÈ¡MÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØíAѬĤ°ÅÕ½Ðì¨ÅÕ½Ðì¤(íø$$
½¹Í½±]ɥѡMÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØíAѬĤµÀì1¤(íø$$
½¹Í½±]ɥѡMÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØíAÑ° ÀÌØíAÑ´ÀÌØíAѤ¤µÀì1¤($%%ÀÌØíAÑÐì ÀÌØíAѬȤ=È ÀÌØíAÑô ÀÌØíAѬȤ¹ÀÌØíÍY°ôÅÕ½Ðí¥±YÉÍ¥½¸ÅÕ½Ðì¤Q¡¸ì´´9µ©Ù±Õ¨¨¸M¼ÍÑÉб½½­¥¹ÐÍÉ¡ÉÑÈÑȸ%Ñ¡Ð($$$ÀÌØíÌÐôMÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØíAÑ° ÀÌØíAÑ´ÀÌØíAѤ¤ì´´¡ÉÑȥ̨ѡ¸¥ÐÌäíÌ9µ¨¨¨Ý¡¥ µ¹ÌÑ¡ÉÌäíÌ($$$ÀÌØíÌÐôMÑÉ¥¹IÁ± ÀÌØíÌаÅÕ½Ðì¨ÅÕ½Ðì°ÅÕ½ÐìÅÕ½Ðì¤ì´µ¹¼Ù±Õ½ÈÑ¡ÐÍÁ¥¥ÁɽÁÉÑä¸($$%%MÑÉ¥¹%¹MÑÈ ÀÌØíÌа
¡È Ĥ°Ä¤ôÀQ¡¸IÑÕɸÀÌØíÌÐì´´¡¬½È
¡È Ĥݡ¥ ͵ÌѼ½Õ¹($%¹%ìÑݸٱÕ̸%¥ÐÌäíÌ¥¸Ñ¡ÍÑÉ¥¹Ñ¡Ðµ¹Ìѡɥ̹¼Ù±Õ½È($$(%¹%(%IÑÕɸÅÕ½ÐìÅÕ½Ðì)¹Õ¹ìôôÐí}Ñ%¹¼(ì´´´´´´´´´´´´´´Í¥µÁ±¥¥ÙÉÍ¥½¸½}Ñ   åÑMÑÉ¥¹½ÈÑ¡¥Ì
±Í̸´´´´´´´´´´´´´´´´´´´´´)Õ¹}Ñ  åÑMÑÉ¥¹ ÀÌØíÍMÑÈ°ÀÌØíM¹¥ÁU¹¥½¤(%1½°ÀÌØíÍIаÀÌØí¥1¸°ÀÌØí¥°ÀÌØí¥1¸È°ÀÌØíÉlÉt($ì=¸ÉɽÈIÍÕµ9áÐ($ÀÌØí¥1¸ÈôÀ(%% ÀÌØíM¹¥ÁU¹¥½ô±Í¤Q¡¸($%I¥´ÀÌØíÉmMÑÉ¥¹1¸ ÀÌØíÍMÑȤt($%½ÈÀÌØí¥1¸ôÄQ¼MÑÉ¥¹1¸ ÀÌØíÍMÑȤ($$$ÀÌØí¥ôÍ¡MÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØí¥1¸°Ä¤¤($$%%ÀÌØí¥ôÀQ¡¸ÀÌØí¥ôÐÈì´´½¹ÙÉÑÌÀµåÑѼ¨($$$í%U    ½Õ¹ ÀÌØíȤÐìÀÌØí¥1¸´ÄQ¡¸($$$ÀÌØíÉlÀÌØí¥1¸´Åtô
¡È ÀÌØí¥¤($%9áÐ(%±Í($%I¥´ÀÌØíÉl¡MÑÉ¥¹1¸ ÀÌØíÍMÑȤ¼È¤t($%½ÈÀÌØí¥1¸ôÄQ¼MÑÉ¥¹1¸ ÀÌØíÍMÑȤMÑÀÈ($$$ÀÌØí¥ôÍ¡MÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØí¥1¸°Ä¤¤($$%%ÀÌØí¥ôÀQ¡¸ÀÌØí¥ôÐÈì´´½¹ÙÉÑÌÀµåÑѼ¨($$$ÀÌØíÉlÀÌØí¥1¸Étô
¡È ÀÌØí¥¤($$$ÀÌØí¥1¸ÈôÀÌØí¥1¸È¬Ä($%9áÐ(%¹%(%IÑÕɸ})½¥¸ ÀÌØíÈ°ÅÕ½ÐìÅÕ½Ðì¤)¹Õ¹ìôôÐí}Ñ    åÑMÑÉ¥¹(ì´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´´M¥µÁ±¥¥ÙÉÍ¥½¸½}ÑÉÉ临´´´´´´´´´´´´´´´´´´´´´´)Õ¹}ÑÉÉä ÀÌØíÍMÑȤ(%¥´ÀÌØí¥°ÀÌØí1¸Ä°ÀÌØí1¸È°ÀÌØíMÑÉlÉt($ì=¸ÉɽÈIÍÕµ9áÐ($ÀÌØí1¸ÄôMÑÉ¥¹1¸ ÀÌØíÍMÑȤ(%%ÀÌØí1¸ÄÐìÄQ¡¸I¥´ÀÌØíMÑÉl ÀÌØí1¸Ä¤t(%½ÈÀÌØí¥ôÄQ¼ÀÌØí1¸Ä($$ÀÌØíMÑÉlÀÌØí¥´ÅtôÍ¡MÑÉ¥¹5¥ ÀÌØíÍMÑÈ°ÀÌØí¥°Ä¤¤(%9áÐ(%IÑÕɸÀÌØíMÑÈ)¹Õ¹ìôôÐí}ÑÉÉä(ì´´´´´´´´´´´´´´´´´´´´ÉÑÕɸ¹ÕµÈɽ´È½ÈÐåÑ̸´´´´´´´´´´´´´´´)Õ¹}Ñ9յɽµ   åÑÌ ÀÌØí åÑ̤(%¥´ÀÌØí9Õ´Ä($ìÉȹ
±È($ì=¸ÉɽÈIÍÕµ9áÐ($í}Ñ9յɽµ   åÑÌô´Ä(%%U    ½Õ¹ ÀÌØí åÑ̤ÐìÄQ¡¸($$ÀÌØí9Õ´Äô ÀÌØí    åÑÍlÁt¬ÀÌØí    åÑÍlÅt¨ÈÔؤ($%%¡U ½Õ¹ ÀÌØí åÑ̤Ðì̤Q¡¸($$$ÀÌØí9Õ´ÄôÀÌØí9մĬ ÀÌØí    åÑÍlÉt¨ØÔÔÌؤ¬ ÀÌØí åÑÍlÍt¨ÄØÜÜÜÈÄؤ($%¹%($%IÑÕɸÀÌØí9Õ´Ä(%¹%)¹Õ¹ìôôÐí}Ñ9յɽµ åÑÌ()Õ¹})½¥¸ ÀÌØíMÑÉ(°ÀÌØíͱ¥´ôÅÕ½ÐìÅÕ½Ðì¤($íµ¥µ¥Y)½¥¸½µµ¹¡ÉÉäѼÍÑÉ¥¹Ý¥Ñ ±¥µ¥ÑȤ(%1½°ÀÌØíÍQµÀ(%%%ÍÉÉä ÀÌØíMÑÉ(¤Q¡¸($%½ÈÀÌØíàôÀQ¼U   ½Õ¹ ÀÌØíMÑÉ(¤´Ä($$$ÀÌØíÍQµÀôÀÌØíÍQµÀµÀìÀÌØíMÑÉ)lÀÌØíátµÀìÀÌØíͱ¥´($%9áÐ($$í
½¹Í½±]É¥Ñ ÅÕ½Ðí)½¥¸ÀÌØíÍQµÀôÅÕ½ÐìµÀìÀÌØíÍQµÀµÀì1¤($%IÑÕɸÀÌØíÍQµÀ(%¹%(%MÑÉÉ½È Ä¤(%IÑÕɸÅÕ½ÐìÅÕ½Ðì)¹Õ¹ìôôÐí})½¥¸()Õ¹}M­¥À ÀÌØí¡¥±°ÀÌØíåÑ̤($íµ¥µ¥M

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Link to comment
Share on other sites

Here's an attempt to populate the resource properties from the file info of the file.

my testing so far seems to work on patch files, autoit exes modified with resource hacker, and autoit exes not modified with resource hacker

Tested against a couple of non-autoit exe's also.

;-- This script includes a class and a demo. Drop any PE file onto the script (EXE, DLL, OCX)
;-- to get file properties. The class, ClsProps, is a complete set of all functions needed
;-- get file properties using only VBS and the Textstream object.
;-- The file properties returned are those that are found when a file is right-clicked,
;-- Properties menu is clicked, and Version tab is selected. This information
;-- is included in most PE (portable executable) files.

;-- Thank you to Ed Gruberman (http://www.rjump.com) for help with this code.
;-- He corrected a bug and also worked out the "aspack" variation whereby some
;-- PE files have been compressed and require a different method to find the version info.  j.

;-- NOTE: This script is written to be compact for pasting into scripts. It uses simplified versions of some functions from
;-- the Textstream Binary Ops and Base 64 download, using only the functionality needed to get file version info.,
;--  in order to keep this class as small as possible. If you want to use functions such as _GetArray or _GetByteString
;-- you may want to download the other package. It provides a fairly complete set of methods for working with binary files.

;-- Demo script --------------------
;Converted to AutoItV3   Steve Podhajecki [eltorro] steve@ocotillo.sytes.net
; Modified by Steve Podhajecki, Gary Frost
;~ Global $props[18] = ["CompanyName", "FileDescription", "FileVersion", "ProductName", "LegalCopyright", _
;~      "OriginalFilename", "Installer Engine", "Applies to", "Build Date", "Installation Type", _
;~      "Installer Version", "InternalName", "KB Article Number", "Support Link", "Package Type", _
;~      "Proc. Architecture", "Self-Extractor Version", "DisplayName"]
;See OnAutoItStart()
;$Arg = "Windows2000-KB914388-x86-ENU.EXE"
;$Arg= "C:\Windows\System32\cmdhere.dll"
;$Arg = "C:\Windows\System32\ZlibTool.ocx"
;$Arg = "C:\Windows\System32\Calc.exe"

;-- End demo script ------------------------------------------------------------

;-- //////////////////////// Start Class:   ClsProps   ///////////////////////////////////////////////
;
;  Functions in this class. (All functions are needed for getting file version information.)
;
;   Public Function _GetVersionInfo($sFilePath, $ARet2)  - returns version information For PE files.
;                                                                On success $ARet2 returns array(5) containing version info. strings for file.
;    Function return error codes:    0 = success.      1 = invalid file path.      2 = no .rsrc table listed in section table.
;    3 = failed to find version info.       4 = not a PE file.       5 = file is a 16-bit executable. ("NE" file rather than "PE")
;
;     Private (internal) functions:
;        _GetArray(StringIn) - convert a string to an array of byte values.
;        _GetByteString(StringIn, $SnipUnicode) - convert a string to a manageable version. If $SnipUnicode = True then get only every 2nd byte.
;        _GetNumFromBytes(array) - takes array of ubound 1 or 3. return numeric value for 2 or 4 bytes.
;
;
;
;
;
;----------------////////////  --- BEGIN Class HERE ---  /////////////////////-------------------------------------------

Func OnAutoItStart()
    ;uncomment this for drag to or commandline usage.
    If $CmdLine[0] = 0 Then
        MsgBox(266288, @ScriptName, "Drop A PE file [EXE-DLL-OCX] onto this script to get version information." & _
                @CRLF & "Commad Prompt Usage:" & @CRLF & @ScriptName & " " & "myfile.[exe,dll,ocx]")
        Exit
    EndIf
    Global $Arg = $CmdLine[1]
    _Main()
EndFunc   ;==>OnAutoItStart

Func _Main()
    Global $sAst, $ANums
    Global $Arg, $i2, $AReturn, $s
    Global $props[1]
    
    $i2 = _GetVersionInfo($Arg, $AReturn)
    Switch $i2
        Case 1
            MsgBox(266288, @ScriptName, "File path not valid")
        Case 2
            MsgBox(266288, @ScriptName, "Unable to find Resource table header in file.")
        Case 3
            MsgBox(266288, @ScriptName, "Unable to find file version info. in file.")
        Case 4
            MsgBox(266288, @ScriptName, "This is not a PE file.")
        Case 5
            MsgBox(266288, @ScriptName, "This is a 16-bit executable. It is not a PE file.")
        Case 0  ; success
            $s = ""
            For $x = 0 To UBound($props) - 1
                $s &= $props[$x] & ": " & $AReturn[$x] & @CRLF
            Next
            MsgBox(266288, @ScriptName, $Arg & @CRLF & @CRLF & $s)
    EndSwitch
EndFunc   ;==>_Main


;-- The public function in this class: _GetVersionInfo -----------------------------------------
Func _GetVersionInfo($sFilePath, ByRef $ARet2)  ;-- return array(5)
    Local $ARet, $s1, $sB, $Pt1, $sRes, $A1, $A4[4], $A2[4], $LocRes, $VLocRes, $SizeRes, $iOff, $Boo, $sVerString, $sMarker
    Local $iNum1, $iNum2, $iReadPt, $iNum3, $LocAspack, $VLocAspack, $VIOffset, $ReadOffset, $BooAspack
    ;   On Error Resume Next
    If Not FileExists($sFilePath) Then
        Return 1  ;bad path.
    EndIf
    $sRes = ".rsrc"
    $sVerString = "VS_VER"
    $BooAspack = False
    
    
    $file = FileOpen($sFilePath, 0)
    $s1 = FileRead($sFilePath, 2048)
    FileClose($file)
    $file = 0
    ;ConsoleWrite($s1)
    $A1 = _GetArray(StringMid($s1, 61, 2))  ;-- get number value at offset 60 that points to PE signature address.
    
    $iNum1 = (_GetNumFromBytes($A1) + 1)     ;-- get offset of "PE00"
    $sB = _GetByteString($s1, False)  ;-- get a workable string with Chr(0) replaced by "*".
    $sMarker = StringMid($sB, $iNum1, 4)
;~  ConsoleWrite("$sMarker ="&$sMarker&@LF)
    If ($sMarker <> "PE**") Then
        If StringLeft($sMarker, 2) = "NE" Then
            Return 5  ;-- 16 bit.
        Else
            Return 4  ;-- no PE signature found.
        EndIf
    EndIf
    
    $Pt1 = StringInStr($sB, $sRes)   ;-- find .rsrc table.
    If ($Pt1 = 0) Then
        Return 2  ;no resource table header found.
    EndIf
    $Pt1 = $Pt1 + 12  ;--  size of raw data is 4 bytes at offset of 16 into the .rsrc table.
    $A1 = _GetArray(StringMid($s1, $Pt1, 12))  ;-- get the same string as a numeric array to Read offset numbers.
    For $iOff = 0 To 3
        ;ConsoleWrite("$iOff ="&$iOff&@LF)
        $A4[$iOff] = $A1[$iOff]
    Next
    $VLocRes = _GetNumFromBytes($A4)
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4) ;--size of resource section in bytes.
    For $iOff = 0 To 3
        $A4[$iOff] = $A1[$iOff + 8]
    Next
    $LocRes = _GetNumFromBytes($A4)    ;-- offset location of resource section.
    $Pt1 = StringInStr(1, $sB, ".aspack")   ;-- find .rsrc table.
    If ($Pt1 > 0) Then
        $BooAspack = True
        $Pt1 = $Pt1 + 12    ;--  virtual offset is first 4 bytes; raw offset is bytes 9-12.
        $A1 = _GetArray(StringMid($s1, $Pt1, 12))
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff]
        Next
        $VLocAspack = _GetNumFromBytes($A4)
        For $iOff = 0 To 3
            $A4[$iOff] = $A1[$iOff + 8]
        Next
        $LocAspack = _GetNumFromBytes($A4)
    EndIf
    
    $Boo = False
    $file = FileOpen($sFilePath, 0)
    ;MsgBox(0, "$LocRes", "$LocRes+12 =" & $LocRes + 12)
;~     ConsoleWrite("$LocRes+12 =" & $LocRes + 12 & @CRLF)
    _Skip($file, $LocRes + 12)
    $s1 = FileRead($file, 2)  ;-- Read bytes 13,14 to get number of named resource types.
    $iNum1 = Asc($s1)       ;-- number of names.
    ;    ConsoleWrite("$iNum1 =" & $iNum1 & @LF)
    $s2 = FileRead($file, 2)  ;-- Read bytes 15,16 to get number of numbered resource types.
    
    $iNum2 = Asc($s2);-- number of nums.
    ;    ConsoleWrite("$iNum2 =" & $iNum2 & @LF)
    If $iNum2 = 0 Then ;-- no numbered entries. have to quit here.
        Return 3
    EndIf
    
    
    If ($iNum1 > 0) Then _Skip($file, $iNum1 * 8) ;-- Skip past named entries.
    $iReadPt = $LocRes + 16 + ($iNum1 * 8)  ;-- update file offset variable because this will be needed.
    ;ConsoleWrite("$iReadPt ="& $iReadPt&@LF)
    $Boo = False
    For $iOff = 1 To $iNum2
        $s1 = FileRead($file, 8)
        $iReadPt = $iReadPt + 8
        If (Asc($s1) = 16) Then  ;-- this is version info. entry.
            $Boo = True
            ExitLoop
        EndIf
    Next
    If ($Boo = False) Then  ;-- have to quit. no version info. entry found.
        
        ;ConsoleWrite("Return point 1" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
    
    $A1 = _GetArray($s1)  ;-- get a byte array for version info entry at top level.
    ;ConsoleWrite("Ubound>>"&UBound($A1))
    $iOff = 0
    $iNum3 = 1
    ;Do
    While 1
        For $iNum1 = 0 To 2  ;-- get offset number to next level from 2nd 4 bytes of entry structure.
            $A4[$iNum1] = $A1[$iNum1 + 4]
        Next
        $A4[3] = 0
        $iNum2 = _GetNumFromBytes($A4)
        
        If ($A1[7] > 127) Then  ;-- high bit was set in entry offset value, so it;s just a pointer to another pointer.
            $iNum2 = $LocRes + $iNum2 + 16
            _Skip($file, $iNum2 - $iReadPt)   ;- 1)
            $s1 = FileRead($file, 8)
            $iReadPt = $iReadPt + (($iNum2 - $iReadPt) + 8)
            $A1 = _GetArray($s1)
        Else  ;-- this is the offset of version info offset info.!
            $iOff = ($iNum2 + $LocRes)
            ;ExitLoop
            ExitLoop
        EndIf
        $iNum3 = $iNum3 + 1
        If ($iNum3 > 10) Then ExitLoop
    WEnd
    ;Loop
    If ($iOff = 0) Then  ;-- have to quit. no final offset found.
        ;ConsoleWrite("Return point 2" & @LF)
        Return 3  ;failed to find version info in resource table.
        
    EndIf
    _Skip($file, $iOff - $iReadPt)
    $s1 = FileRead($file, 8)
    $iReadPt = $iReadPt + (($iOff - $iReadPt) + 8)
    $A1 = _GetArray($s1)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1]
    Next
    $VIOffset = _GetNumFromBytes($A4)  ;--offset of version info. given in .rsrc section.
    $ReadOffset = (($VIOffset - $VLocRes) + $LocRes)
    For $iNum1 = 0 To 3
        $A4[$iNum1] = $A1[$iNum1 + 4]
    Next
    $SizeRes = _GetNumFromBytes($A4)
    _Skip($file, $ReadOffset - $iReadPt)
    $s1 = FileRead($file, $SizeRes)  ;-- read out the entire FileVersionInfo data area.
    FileClose($file)
    $file = 0
    $sB = _GetByteString($s1, True) ;-- snip unicode.
    $Pt1 = StringInStr($sB, $sVerString)
    If ($Pt1 > 0) Then        ;-- "VS_VER" was found, so process the string and quit.
        $ARet = _ProcessRes($sB)
        $ARet2 = $ARet
        Return 0  ; ok
    ElseIf ($BooAspack = True) Then   ;-- if "VS_VER" was not found but there is an "aspack" section then try that.
        $ReadOffset = (($VIOffset - $VLocAspack) + $LocAspack)  ;-- calculate a new file version info data offset.
        $file = FileOpen($sFilePath, 0)  ;-- The file was closed and is now re-opened here. Keeping the file
        _Skip($file, $ReadOffset)                            ;-- open "just in case" wouldn;t have helped because the file pointer
        $s1 = FileRead($file, $SizeRes)                     ;-- for this read may be further back thean the pointer was when the file
        FileClose($file) ;-- was closed. So rather than try to sort out the read point, the file is just
        $file = 0;-- opened fresh and Skip is used.
        $sB = _GetByteString($s1, True)
        $Pt1 = StringInStr($sB, $sVerString)
        If ($Pt1 > 0) Then
            $ARet = _ProcessRes($sB)
            $ARet2 = $ARet
            Return 0  ; ok
        Else
            ;ConsoleWrite("Return point 3" & @LF)
            Return 3  ;failed to find version info in resource table.
        EndIf
    Else
        ;ConsoleWrite("Return point 4" & @LF)
        Return 3  ;failed to find version info in resource table.
    EndIf
EndFunc   ;==>_GetVersionInfo

Func _ProcessRes($sDat)
    ; find where the resource info starts
    Local $info_ptr = StringInStr($sDat, "StringFileInfo") + StringLen("StringFileInfo")
    Local $s_props = StringMid($sDat, $info_ptr)
    Local $occurance = 2
    While 1
        $info_ptr = StringInStr($s_props, Chr(1), 0, $occurance) + 1 ; find the beginning of a property name
        $s_prop = StringMid($s_props, $info_ptr)
        $prop_ptr = StringInStr($s_prop, "*") ; find the end of a property name
        If @error Then ExitLoop
        $s_prop = StringMid($s_prop, 1, $prop_ptr - 1)
        If Not StringLen($s_prop) Then ExitLoop ; no more resources
        If $s_prop = "VarFileInfo" Then ExitLoop ; no more resources
        $occurance += 1
        ReDim $props[$occurance - 2]
        $props[$occurance - 3] = $s_prop ; resize and populate array with resource names
    WEnd
    Dim $AInfo[UBound($props) ]
    ;      On Error Resume Next
    For $x = 0 To UBound($props) - 1
        $AInfo[$x] = _GetInfo($sDat, $props[$x])
    Next
    Return $AInfo
EndFunc   ;==>_ProcessRes

Func _GetInfo($sStr, $sVal)
    ; had to rewrite this function because of incompatiblities
    ;between AutoIt3 and Vb string functions.
    Dim $Pta, $Ptb, $LenVal, $s4, $occurance = 1
    $LenVal = StringLen($sVal) + 1  ;-- length of info string: "CompanyName" = 11
    $Pta = StringInStr($sStr, $sVal)  ;-- find string name.
;~  ConsoleWrite(String(StringMid($sStr, $Pta - 1, 1)) & @LF)
    If ($Pta > 0) Then
        $Pta = $Pta + $LenVal
        $Ptb = $Pta + StringInStr(StringMid($sStr, $Pta + 1), "*")
;~        ConsoleWrite(StringMid($sStr, $Pta + 1) & @LF)
;~        ConsoleWrite(StringMid($sStr, $Pta, ($Ptb - $Pta)) & @LF)
        If $Ptb > ($Pta + 2) And $sVal <> "FileVersion" Then
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))
            $s4 = StringReplace($s4, "*", "")
            If StringInStr($s4, Chr(1), 1) = 0 Then Return $s4
        ElseIf $sVal = "FileVersion" Then ; deal with file version
            $s4 = StringMid($sStr, $Pta, ($Ptb - $Pta))
            If $Ptb = ($Pta + 2) Then
                $s4 &= '.0.0.0'
            EndIf
            $s4 = StringReplace($s4, "*", "")
            $s4 = StringReplace($s4, ",", ".")
            $s4 = StringStripWS($s4, 8)
            If StringInStr($s4, Chr(1), 1) = 0 Then Return $s4   ;-- check for Chr(1) which seems to be found
        EndIf
        
    EndIf
    Return ""
EndFunc   ;==>_GetInfo
;-------------- simplified version of _GetByteString For this Class. ---------------------
Func _GetByteString($sStr, $SnipUnicode)
    Local $sRet, $iLen, $iA, $iLen2, $A2[2]
    ;    On Error Resume Next
    $iLen2 = 0
    If ($SnipUnicode = False) Then
        ReDim $A2[StringLen($sStr) ]
        For $iLen = 1 To StringLen($sStr)
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            ;If UBound($A2) > $iLen - 1 Then
            $A2[$iLen - 1] = Chr($iA)
        Next
    Else
        ReDim $A2[ (StringLen($sStr) / 2) ]
        For $iLen = 1 To StringLen($sStr) Step 2
            $iA = Asc(StringMid($sStr, $iLen, 1))
            If $iA = 0 Then $iA = 42 ;-- converts 0-byte to *
            $A2[$iLen2] = Chr($iA)
            $iLen2 = $iLen2 + 1
        Next
    EndIf
    Return _Join($A2, "")
EndFunc   ;==>_GetByteString
;-------------------------------- Simplified version of _GetArray. -----------------------
Func _GetArray($sStr)
    Dim $iA, $Len1, $Len2, $AStr[2]
    ;  On Error Resume Next
    $Len1 = StringLen($sStr)
    If $Len1 > 1 Then ReDim $AStr[ ($Len1) ]
    For $iA = 1 To $Len1
        $AStr[$iA - 1] = Asc(StringMid($sStr, $iA, 1))
    Next
    Return $AStr
EndFunc   ;==>_GetArray
;-------------------- return a number from 2 or 4 bytes. ---------------
Func _GetNumFromBytes($ABytes)
    Dim $Num1
    ;    Err.Clear
    ;        On Error Resume Next
    ;_GetNumFromBytes = -1
    If UBound($ABytes) > 1 Then
        $Num1 = ($ABytes[0] + $ABytes[1] * 256)
        If (UBound($ABytes) > 3) Then
            $Num1 = $Num1 + ($ABytes[2] * 65536) + ($ABytes[3] * 16777216)
        EndIf
        Return $Num1
    EndIf
EndFunc   ;==>_GetNumFromBytes

Func _Join($aStrJ, $sDelim = "")
    ;mimic VB Join command (array to string with delimiter)
    Local $sTemp
    If IsArray($aStrJ) Then
        For $x = 0 To UBound($aStrJ) - 1
            $sTemp = $sTemp & $aStrJ[$x] & $sDelim
        Next
        ;ConsoleWrite("Join $sTemp =" & $sTemp & @LF)
        Return $sTemp
    EndIf
    SetError(1)
    Return ""
EndFunc   ;==>_Join

Func _Skip($hfile, $bytes)
    ;mimic FSO.skip
    Local $temp = FileRead($hfile, $bytes)
    If @error Then Return 0
    Return 1
EndFunc   ;==>_Skip

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...