AutoHotkey Community

It is currently May 25th, 2012, 3:38 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 29 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: March 14th, 2006, 3:52 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
PhiLho wrote:
I found an interesting article by Microsoft itself! They give a DLL (by actually an ActiveX) to access Office document properties. Alas, you need Com to use it. Perhaps one can write VBScript or JScript code to use it.
From the MS website:
Quote:
The Dsofile.dll sample file is an in-process ActiveX component for programmers that use Microsoft Visual Basic .NET or the Microsoft .NET Framework. You can use this in your custom applications to read and to edit the OLE document properties that are associated with Microsoft Office files, such as the following:• Microsoft Excel workbooks
• Microsoft PowerPoint presentations
• Microsoft Word documents
• Microsoft Project projects
• Microsoft Visio drawings
• Other files without those Office products installed
The source code (C++) for the DLL is coming with the download, so I guess that it could be translated into AHK or included into AHK.

And it has all the abilities. :) With the code form wOxxOm (first post) the item of the Planned Features list
Quote:
New command FileGet/Set or FileGetProperties to retrieve and set things from a file's property sheet (title, author, permissions, etc.)
is getting closer. :)

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Great!
PostPosted: March 15th, 2006, 8:51 am 
Offline

Joined: July 30th, 2004, 8:50 pm
Posts: 192
:) Great script, wOxxOm!

Man I'm glad I gave up WinAPI! Can you understand why it's got to be so complicated? You've got to love AutoHotkey!

I just added it to my CloseMany tool at http://www.donationcoders.com/skrommel, and it's much faster than ShowVer, and it doesn't crash!

You should clean up the code by removing some of the |s in the FileType line, and adding a description next to the |s, as in |FileVersion:. This combined with output to standard out and you've got a tool many want.

Skrommel


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 24th, 2006, 5:22 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
toralf wrote:
PhiLho wrote:
I found an interesting article by Microsoft itself! They give a DLL (by actually an ActiveX) to access Office document properties. Alas, you need Com to use it. Perhaps one can write VBScript or JScript code to use it.
From the MS website:
Quote:
The Dsofile.dll sample file is an in-process ActiveX component for programmers that use Microsoft Visual Basic .NET or the Microsoft .NET Framework. You can use this in your custom applications to read and to edit the OLE document properties that are associated with Microsoft Office files, such as the following:• Microsoft Excel workbooks
• Microsoft PowerPoint presentations
• Microsoft Word documents
• Microsoft Project projects
• Microsoft Visio drawings
• Other files without those Office products installed
The source code (C++) for the DLL is coming with the download, so I guess that it could be translated into AHK or included into AHK.
Could someone please help me to use this DLL from within AHK with DllCall()?

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 24th, 2006, 6:27 pm 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
toralf wrote:
PhiLho wrote:
They give a DLL (by actually an ActiveX) to access Office document properties. Alas, you need Com to use it. Perhaps one can write VBScript or JScript code to use it.
Could someone please help me to use this DLL from within AHK with DllCall()?

AFAIK, you cannot use an ActiveX with DllCall.

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 18th, 2006, 12:01 am 
Offline

Joined: October 15th, 2006, 2:39 am
Posts: 93
Location: Croatia
Quoting,
http://www.autohotkey.com/forum/viewtopic.php?t=8618
http://www.autohotkey.com/forum/topic13348.html
(I hope this cross-linking isn't too complicated)
It looks like we are in need of functions/ahk features with which one can edit file's metadata/tags.
I also noticed that it seems like Office documents are most easily manipulated, but every other material I searched for (codes, sources, general info) is doomed to c++ or bust.
If this "♣DocumentSummaryInformation" data stream (it smells like unicode to me) could be edited, we would have basics for some real hard-core file manipulations.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 4th, 2007, 2:00 pm 
Offline

Joined: March 19th, 2007, 2:36 pm
Posts: 15
T800 wrote:
It looks like we are in need of functions/ahk features with which one can edit file's metadata/tags.
I also noticed that it seems like Office documents are most easily manipulated, but every other material I searched for (codes, sources, general info) is doomed to c++ or bust.
If this "♣DocumentSummaryInformation" data stream (it smells like unicode to me) could be edited, we would have basics for some real hard-core file manipulations.


I (somewhat successfully) created the following code to operate on this info through brute force (binary stream parsing). Take note of the hyperlinks referenced for data structure and functions used. Using this I can successfully read/write the "category" shown in the Windows Explorer file properties summary tab.

But after getting this far, I've decided to abandon it. Reasons: (1) it only works on NTFS (only tested on XP), (2) doesn't work for "recognized" file types, such as MSOffice documents, (3) my understanding is that Vista is fundamentally different in handling streams, (4) parsing a binary stream in AHK (using text strings) was really difficult compared to the C/C++ programming I'm used to.

Anyway, here it is. Maybe someone else can take this and run with it.

Code:
; read in NTFS alternate stream data
file = % "y:\ahk\test.txt:" Chr(05) "DocumentSummaryInformation" ; includes category
file2 = % "y:\ahk\test.txt:" Chr(05) "SummaryInformation" ; includes title, author, keywords, comments, etc.
res := BinRead(file,data,0,0)
text := Hex2Txt(data)

; parsing SummaryInformation
; credit: http://sedna-soft.de/summary-information-stream/

; get section length
start := 48*2+1
StringMid,out,data,start,8
sectionlen := DWord2Dec(out)

; get date/time stamp length
start := 96*2+1
StringMid,out,data,start,8
datelen := DWord2Dec(out)

; get category text length
start := 96*2+datelen*2-13
StringMid,out,data,start,8
categorylen := DWord2Dec(out)

; extract category text, prompt user to change
StringMid,out,data,96*2+datelen*2-5,categorylen*2+2
category := Hex2Txt(out)
InputBox, newcat, "Category", , , , , , , , ,%category%

; assemble new binary stream
StringLeft, dataout1, data, 48*2
StringMid, dataout2, data, 48*2+9, datelen*2+74

cattext := Txt2Hex(newcat)
catlen := StrLen(newcat)+1
catlentext := Dec2DWord(catlen)
sectionlen := 67+catlen
sectionlentext := Dec2DWord(sectionlen)
dataout = %dataout1%%sectionlentext%%dataout2%%catlentext%%cattext%00000000

; write new binary stream
MsgBox %data%`n`n%dataout%
res := BinWrite(file,dataout,0,0)
;MsgBox ErrorLevel = %ErrorLevel%`nBytes Written = %res%`n`n%dataout%

ExitApp


; BinWrite/BinRead code credit: http://www.autohotkey.com/forum/viewtopic.php?t=4546

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinWrite ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|  - Open binary file
|  - (Over)Write n bytes (n = 0: all)
|  - From offset (offset < 0: counted from end)
|  - Close file
|  data -> file[offset + 0..n-1], rest of file unchanged
|  Return #bytes actually written
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinWrite(file, data, n=0, offset=0)
{
   ; Open file for WRITE (0x40..), OPEN_ALWAYS (4): creates only if it does not exists
   h := DllCall("CreateFile","str",file,"Uint",0x40000000,"Uint",0,"UInt",0,"UInt",4,"Uint",0,"UInt",0)
   IfEqual h,-1, SetEnv, ErrorLevel, -1
   IfNotEqual ErrorLevel,0,Return,0 ; couldn't create the file

   m = 0                            ; seek to offset
   IfLess offset,0, SetEnv,m,2
   r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
   IfEqual r,0, SetEnv, ErrorLevel, -3
   IfNotEqual ErrorLevel,0, {
      t = %ErrorLevel%              ; save ErrorLevel to be returned
      DllCall("CloseHandle", "Uint", h)
      ErrorLevel = %t%              ; return seek error
      Return 0
   }

   TotalWritten = 0
   m := Ceil(StrLen(data)/2)
   If (n <= 0 or n > m)
       n := m
   Loop %n%
   {
      StringLeft c, data, 2         ; extract next byte
      StringTrimLeft data, data, 2  ; remove  used byte
      c = 0x%c%                     ; make it number
      result := DllCall("WriteFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Written,"UInt",0)
      TotalWritten += Written       ; count written
      if (!result or Written < 1 or ErrorLevel)
         break
   }

   IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

   h := DllCall("CloseHandle", "Uint", h)
   IfEqual h,-1, SetEnv, ErrorLevel, -2
   IfNotEqual t,,SetEnv, ErrorLevel, %t%

   Return TotalWritten
}

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|  - Open binary file
|  - Read n bytes (n = 0: all)
|  - From offset (offset < 0: counted from end)
|  - Close file
|  data (replaced) <- file[offset + 0..n-1]
|  Return #bytes actually read
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinRead(file, ByRef data, n=0, offset=0)
{
   h := DllCall("CreateFile","Str",file,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0)
   IfEqual h,-1, SetEnv, ErrorLevel, -1
   IfNotEqual ErrorLevel,0,Return,0 ; couldn't open the file

   m = 0                            ; seek to offset
   IfLess offset,0, SetEnv,m,2
   r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
   IfEqual r,0, SetEnv, ErrorLevel, -3
   IfNotEqual ErrorLevel,0, {
      t = %ErrorLevel%              ; save ErrorLevel to be returned
      DllCall("CloseHandle", "Uint", h)
      ErrorLevel = %t%              ; return seek error
      Return 0
   }

   TotalRead = 0
   data =
   IfEqual n,0, SetEnv n,0xffffffff ; almost infinite

   format = %A_FormatInteger%       ; save original integer format
   SetFormat Integer, Hex           ; for converting bytes to hex

   Loop %n%
   {
      result := DllCall("ReadFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Read,"UInt",0)
      if (!result or Read < 1 or ErrorLevel)
         break
      TotalRead += Read             ; count read
      c += 0                        ; convert to hex
      StringTrimLeft c, c, 2        ; remove 0x
      c = 0%c%                      ; pad left with 0
      StringRight c, c, 2           ; always 2 digits
      data = %data%%c%              ; append 2 hex digits
   }

   IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

   h := DllCall("CloseHandle", "Uint", h)
   IfEqual h,-1, SetEnv, ErrorLevel, -2
   IfNotEqual t,,SetEnv, ErrorLevel, %t%

   SetFormat Integer, %format%      ; restore original format
   Totalread += 0                   ; convert to original format
   Return TotalRead
}


; Txt2Hex/Hex2Txt code credit: http://www.autohotkey.com/forum/viewtopic.php?t=17928

Txt2Hex(Txt) {
format := A_FormatInteger
StringSplit, TxtArray, Txt
loop, %TxtArray0%
   {
   CurrentTxt := TxtArray%A_Index%
   blah := Asc(CurrentTxt)
   SetFormat, Integer, Hex
   Hex := Asc(CurrentTxt)
   SetFormat, Integer, Decimal
   StringReplace, Hex, Hex, 0x,,All
   If StrLen(Hex) = 1
      {
      Hex := Hex . "0"
      }
   Hex%A_Index% := Hex
   }
Hex=
Loop, %TxtArray0%
   {
   Hex := Hex . Hex%A_Index%
   }
SetFormat, Integer, %Format%
return %Hex%
}

Hex2Txt(Hex) {
format := A_FormatInteger
go=1
Txt=
HexLen := StrLen(Hex)
Loop, %HexLen%
   {
   If go=1
   {
   go=0
   HexSet := "0x" . SubStr(Hex, A_Index, 2)
   SetFormat, Integer, Decimal
   HexSet += 0
   Txt := Txt . Chr(HexSet)
   }
   else
   {
   go=1
   }
   }
SetFormat, Integer, %Format%
return %Txt%
}

DWord2Dec(Txt) {

;convert to big endian
byte0 := SubStr(Txt,1,2)
byte1 := SubStr(Txt,3,2)
byte2 := SubStr(Txt,5,2)
byte3 := SubStr(Txt,7,2)
hex := byte3 . byte2 . byte1 . byte0

;convert to decimal
result := "0x" . hex
result += 0

; return resulting decimal value
return result
}

Dec2DWord(Val) {

;convert decimal to hex
SetFormat, integer, hex
Val += 0
SetFormat, integer, d

;extract text
Txt := SubStr(Val,3)
len := StrLen(Txt)

; convert to byte-wise little endian format
if (len=1)
   DWord = 0%Txt%000000
else if (len=2)
   DWord = %Txt%000000
else if (len=3)
   DWord := SubStr(Txt,2,2) . "0" . SubStr(Txt,3,1) . "0000"
else if (len=4)
   DWord := SubStr(Txt,3,2) . SubStr(Txt,1,2) . "0000"
else if (len=5)
   DWord := SubStr(Txt,4,2) . SubStr(Txt,2,2) . "0" . SubStr(Txt,1,1) . "00"
else if (len=6)
   DWord := SubStr(Txt,5,2) . SubStr(Txt,3,2) . SubStr(Txt,1,2) . "00"
else if (len=7)
   DWord := SubStr(Txt,6,2) . SubStr(Txt,4,2) . SubStr(Txt,2,2) . "0" . SubStr(Txt,1,1)
else if (len=8)
   DWord := SubStr(Txt,7,2) . SubStr(Txt,5,2) . SubStr(Txt,3,2) . SubStr(Txt,1,2)
else
   DWord = 00000000

; return resulting string
return %DWord%
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 8th, 2007, 4:44 pm 
Offline

Joined: March 19th, 2007, 2:36 pm
Posts: 15
Here's DLL that let's you read/write Office summary info:
http://support.microsoft.com/?id=224351


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 8th, 2007, 6:56 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
This streams are good to hide the data.

If you create file and write data into your own stream, it can not be seen very easy. Its size will be 0, if you give it stupid name like "msinst.tmp" and save it in %WINDIR% it will be very hard to find (if not enough, you can mascarade with some real ms temp sht), plus regular file copy will not see the alternate stream, (so file can be fully copied just with right tools). Combined with some ecription, using "accidential private keys" based on the frequency pattern of some unknown song, you can save anytnig you like and only genious will be able to find it, and God to read it.

What is more interesting, AHK script can be created to do all things I mention above (except measuring the average frequency of the song) :D

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 9th, 2007, 6:25 am 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
bobbo wrote:
Here's DLL that let's you read/write Office summary info:
http://support.microsoft.com/?id=224351
Thanks for the link. It is the file toralf mentioned.
It is still an ActiveX DLL, but the interesting new info is that now AutoHotkey supports (indirectly) Com, so Sean, majkinetor or somebody else can use it.
I have only read the first chapter of the Com in C book (very interesting, thanks majkinetor for pointing at it), so I am still unable to help.

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 9th, 2007, 1:16 pm 
Offline

Joined: March 19th, 2007, 2:36 pm
Posts: 15
I didn't figure out how to directly call the DsoFile.dll, so I did the next best thing: created a Visual Basic Script to handle the transactions. Now you can make a command line call to "docprop.vbs" to read and/or set the properties. Examples:

Read: cscript docprop.vbs test.txt
Write: cscript docprop.vbs text.txt Title="My Document's Title"

(You'll need to download DsoFile.dll from the link above to use this script. Also, I've found that cscript is slow to exit; using wscript //b is much faster for batch processing a large number of files using AHK.)

Code:
'docprop.vbs
'Expects input filename, displays properties, sets any properties specified.
'Uses Dsofile.dll, available at http://support.microsoft.com/?id=224351

'Version History:
'v1.0 09May2007 Release

Set objArgs = WScript.Arguments
If objArgs.Count=0 Then
  'no arguments, so echo usage instructions
  Wscript.Echo "Syntax: docpop test.txt title=""doc title"" subject=""doc subject"" author=""author name"" category=""category name"" keywords=""keyword list"" comments=""your comments"""
  Wscript.Quit 0
Elseif InStr(objArgs(0),"?") Then
  'help requested, so echo usage instructions
  Wscript.Echo "Syntax: docpop test.txt title=""doc title"" subject=""doc subject"" author=""author name"" category=""category name"" keywords=""keyword list"" comments=""your comments"""
  Wscript.Quit 0
End If

InputFile = objArgs(0)
Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open(InputFile)

If objArgs.Count = 1 Then
  'just the file name, so only report the current properties
Elseif objArgs.Count > 1 Then
  'properties specified, so set them
  For n = 1 To (objArgs.Count - 1)
    'WScript.Echo n & " = " &  objArgs(n)
    pos = InStr(objArgs(n),"=")
    If InStr(objArgs(n),"Title") Then
      objFile.SummaryProperties.Title = Right(objArgs(n),Len(objArgs(n))-pos)
    Elseif InStr(objArgs(n),"Subject") Then
      objFile.SummaryProperties.Subject = Right(objArgs(n),Len(objArgs(n))-pos)
    Elseif InStr(objArgs(n),"Author") Then
      objFile.SummaryProperties.Author = Right(objArgs(n),Len(objArgs(n))-pos)
    Elseif InStr(objArgs(n),"Category") Then
      objFile.SummaryProperties.Category = Right(objArgs(n),Len(objArgs(n))-pos)
    Elseif InStr(objArgs(n),"Keywords") Then
      objFile.SummaryProperties.Keywords = Right(objArgs(n),Len(objArgs(n))-pos)
    Elseif InStr(objArgs(n),"Comments") Then
      objFile.SummaryProperties.Comments = Right(objArgs(n),Len(objArgs(n))-pos)
    Elseif InStr(objArgs(n),"Title") Then
      objFile.SummaryProperties.Title = Right(objArgs(n),Len(objArgs(n))-pos)
    End If
  Next
  objFile.Save
End If

'report properties of InputFile
Wscript.Echo "File = " & InputFile &_
  vbNewLine & "Title = " & objFile.SummaryProperties.Title &_
  vbNewLine & "Subject = " & objFile.SummaryProperties.Subject &_
  vbNewLine & "Author = " & objFile.SummaryProperties.Author &_
  vbNewLine & "Category = " & objFile.SummaryProperties.Category &_
  vbNewLine & "Keywords = " & objFile.SummaryProperties.Keywords &_
  vbNewLine & "Comments = " & objFile.SummaryProperties.Comments
Wscript.Quit 0


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2008, 3:58 pm 
Offline

Joined: December 14th, 2005, 3:08 pm
Posts: 219
bobbo wrote:
Code:
      objFile.SummaryProperties.Title = Right(objArgs(n),Len(objArgs(n))-pos)


This only gets the Summary Properties of a Word file.

You'd also need the Custom Properties as a lot of people put their own fields in there

My knowledge of COM and VBS is pretty awful.

But this bit works.

Bits taken from the MS sample FilePRop.frm

Code:
For Each oCustProp In objFile.CustomProperties
      sTmp = oCustProp.Name & ": " & CStr(oCustProp.Value)
      sTmp = sTmp & "   [" & CustTypeName(oCustProp.Type) & "]"
   Next
   
   
'report properties of InputFile
Wscript.Echo "File = " & InputFile &_
  vbNewLine & "Title = " & objFile.SummaryProperties.Title &_
  vbNewLine & "Subject = " & objFile.SummaryProperties.Subject &_
  vbNewLine & "Author = " & objFile.SummaryProperties.Author &_
  vbNewLine & "Category = " & objFile.SummaryProperties.Category &_
  vbNewLine & "Keywords = " & objFile.SummaryProperties.Keywords &_

  vbNewLine & "Custom = " & sTmp &_

  vbNewLine & "Comments = " & objFile.SummaryProperties.Comments
Wscript.Quit 0


Function CustTypeName(lType)

 ' This function simply maps string names to the
 ' VARIANT type of a custom property.
   Select Case lType
      Case 1
         CustTypeName = "String"
      Case 2
         CustTypeName = "Long"
      Case 3
         CustTypeName = "Double"
      Case 4
         CustTypeName = "Boolean"
      Case 5
         CustTypeName = "Date"
      Case Else
         CustTypeName = "Unknown"
   End Select
End Function



_________________
Stuart Halliday


Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 21st, 2009, 2:51 pm 
Offline

Joined: February 7th, 2009, 11:28 pm
Posts: 384
wOxxOm wrote:
This script gets full version information for CompanyName/FileDescription/etc. string version info from executable. Because AHK doesn't include such a capability I took an example in VBA and recoded it in AHK

Code:
; LITTLE DEMONSTRATION: hot to fetch full string version information from
; executable files

oldErrMode:=dllCall("SetErrorMode",uint,1) ; SEM_FAILCRITICALERRORS=0x0001
verExts:="|exe|dll|drv|fon|ttf|vxd|sys|cpl|ocx|"
loop,%winDir%\*,,1
{  splitPath,A_LoopFileLongPath,,,ext
   ifInString,verExts,|%ext%|
   {  count ++
      traytip,,%A_LoopFileLongPath%
      info:=info . A_LoopFileLongPath "`t"
                 . FileGetFullVer(A_LoopFileLongPath,1|2|4|8|0xFFFF,"`t") "`n`n"
      if (count=5)
         break
   }
}
dllCall("SetErrorMode",uint,oldErrMode)

if !info
{  fileSelectFile,file,1
   info:=file "`t" FileGetFullVer(file,1|2|4|8|0x8000,"`t")
}

msgbox %info%
ExitApp


FileGetFullVer(file,verFlags=1,delim="")               ;;
{  ifEqual,delim,,delim=|
; FLAGS: 0x0001 - numeric info
;        0x0002 - file type
;        0x0004 - file description
;        0x0008 - company name
;        0x0010 - FileVersion
;        0x0020 - Comments
;        0x0040 - InternalName
;        0x0080 - LegalCopyright
;        0x0100 - LegalTrademarks
;        0x0200 - OriginalFilename
;        0x0400 - ProductName
;        0x0800 - ProductVersion
;        0x1000 - PrivateBuild
;        0x2000 - SpecialBuild
;        0x4000 - LegalTrademarks1

;        0x8000 - clean-up empty fields

; VersionInfoStrings
;   viPredefinedFirst = 0
;   viLanguage = 0
;   viComments = 1
;   viCompanyName = 2
;   viFileDescription = 3
;   viFileVersion = 4
;   viInternalName = 5
;   viLegalCopyright = 6
;   viLegalTrademarks = 7
;   viOriginalFilename = 8
;   viProductName = 9
;   viProductVersion = 10
;   viPrivateBuild = 11
;   viSpecialBuild = 12
;   viLegalTrademarks1 = 13  'Used by Office apps only?
;   viLegalTrademarks2 = 14  'Used by Office apps only?
;   viPredefinedLast = 14

;typedef struct tagVS_FIXEDFILEINFO
;    0  DWORD dwSignature;
;    4  DWORD dwStrucVersion;
;    8  DWORD dwFileVersionMS;
;    12 DWORD dwFileVersionLS;
;    16 DWORD dwProductVersionMS;
;    20 DWORD dwProductVersionLS;
;    24 DWORD dwFileFlagsMask;
;    28 DWORD dwFileFlags;
;    32 DWORD dwFileOS;
;    36 DWORD dwFileType;
;    40 DWORD dwFileSubtype;
;    44 DWORD dwFileDateMS;
;    48 DWORD dwFileDateLS;

;   MAX_PATH = 260
;   ; ----- VS_VERSION.dwFileFlags -----
;   VS_FFI_SIGNATURE = 0xFEEF04BD
;   VS_FFI_STRUCVERSION = 0x10000
;   VS_FFI_FILEFLAGSMASK = 0x3F
;   ; ----- VS_VERSION.dwFileFlags -----
;   VS_FF_DEBUG = 0x1
;   VS_FF_PRERELEASE = 0x2
;   VS_FF_PATCHED = 0x4
;   VS_FF_PRIVATEBUILD = 0x8
;   VS_FF_INFOINFERRED = 0x10
;   VS_FF_SPECIALBUILD = 0x20
;   ; ----- VS_VERSION.dwFileOS -----
;   VOS_UNKNOWN = 0x0
;   VOS_DOS = 0x10000
;   VOS_OS216 = 0x20000
;   VOS_OS232 = 0x30000
;   VOS_NT = 0x40000
;   VOS_DOS_WINDOWS16 = 0x10001
;   VOS_DOS_WINDOWS32 = 0x10004
;   VOS_OS216_PM16 = 0x20002
;   VOS_OS232_PM32 = 0x30003
;   VOS_NT_WINDOWS32 = 0x40004
;   ; ----- VS_VERSION.dwFileType -----
;   VFT_UNKNOWN = 0x0
;   VFT_APP = 0x1
;   VFT_DLL = 0x2
;   VFT_DRV = 0x3
;   VFT_FONT = 0x4
;   VFT_VXD = 0x5
;   VFT_STATIC_LIB = 0x7
;   ; **** VS_VERSION.dwFileSubtype for VFT_WINDOWS_FONT ****
;   VFT2_FONT_RASTER = 0x1
;   VFT2_FONT_VECTOR = 0x2
;   VFT2_FONT_TRUETYPE = 0x3
;   ; ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_DRV -----
;   VFT2_UNKNOWN = 0x0
;   VFT2_DRV_PRINTER = 0x1
;   VFT2_DRV_KEYBOARD = 0x2
;   VFT2_DRV_LANGUAGE = 0x3
;   VFT2_DRV_DISPLAY = 0x4
;   VFT2_DRV_MOUSE = 0x5
;   VFT2_DRV_NETWORK = 0x6
;   VFT2_DRV_SYSTEM = 0x7
;   VFT2_DRV_INSTALLABLE = 0x8
;   VFT2_DRV_SOUND = 0x9
;   VFT2_DRV_COMM = 0xA

   version=
   dummy:=1
   fiSize:=dllCall("version\GetFileVersionInfoSizeA",str,file,uint,&dummy)
   varSetCapacity(fi,fiSize,0)
   loop,1
   {  if !dllCall("version\GetFileVersionInfoA",str,file, int,0, int,fiSize, uint,&fi)
         break
      if !dllCall("version\VerQueryValueA",uint,&fi, str,"", uintp,fiFFI#, uintp,dummy)
         break
      varSetCapacity(fiFFI,13*4)
      dllCall("RtlMoveMemory",uint,&fiFFI,uint,fiFFI#,uint,13*4)
      version:=iif(verFlags & 1=0,""
                  ,"v" extractInteger(fiFFI,10,0,2) "." extractInteger(fiFFI,8,0,2)
                  . iif(extractInteger(fiFFI,12,0,2)=0,""
                        ,"." extractInteger(fiFFI,14,0,2) "." extractInteger(fiFFI,12,0,2)))
             . iif(verFlags & 2=0,""
                  ,"|" switch(extractInteger(fiFFI,36)+1,""
                        ,"Application","DLL"
                        ,"|" switch(extractInteger(fiFFI,40)+1,"","Printer ","Keyboard "
                              ,"Language ","Display ","Mouse ","Network ","System "
                              ,"Installable ", "Sound ","Comm. ") "driver"
                        ,"|" switch(extractInteger(fiFFI,40),"Raster","Vector","TrueType") " font"
                        ,"|VxD driver", "|Static Lib"))
      if (verFlags & 0xFFFE)
      {  if !dllCall("version\VerQueryValueA",uint,&fi, str,"\VarFileInfo\Translation", uintp,fiTrans#, uintp,dummy)
            break
         ifEqual,dummy,0, break
         fiTrans:=0
         dllCall("RtlMoveMemory",uintP,fiTrans,uint,fiTrans#,uint,4)

         Lang#:=fiTrans & 0xFFFF
         CP#:=fiTrans>>16

         varSetCapacity(lang,256,0)
         dummy:=dllCall("VerLanguageNameA",uint,Lang#, str,lang, uint,256)
         stringLeft,lang,lang,%dummy%

         sSubBlock:= "\StringFileInfo" FmtHex(Lang#,4) . FmtHex(CP#,4) ""
         Company:=verGetStdValue(fi,sSubBlock "CompanyName")
         if !Company
         {  ; Try U.S. English...?
            dummy:="\StringFileInfo\0409" FmtHex(CP#,4) ""
            Company:=verGetStdValue(fi,dummy "CompanyName")
            if (Company)
               sSubBlock:=dummy ; We probably found the MS version bug.
         }

         version:=version
            . iif(verFlags & 4=0,"","|" verGetStdValue(fi,sSubBlock "FileDescription"))
            . iif(verFlags & 8=0,"","|" Company)
            . iif(verFlags & 0x10,"|" verGetStdValue(fi,sSubBlock "FileVersion"),"")
            . iif(verFlags & 0x20,"|" verGetStdValue(fi,sSubBlock "Comments"),"")
            . iif(verFlags & 0x40,"|" verGetStdValue(fi,sSubBlock "InternalName"),"")
            . iif(verFlags & 0x80,"|" verGetStdValue(fi,sSubBlock "LegalCopyright"),"")
            . iif(verFlags & 0x100,"|" verGetStdValue(fi,sSubBlock "LegalTrademarks"),"")
            . iif(verFlags & 0x200,"|" verGetStdValue(fi,sSubBlock "OriginalFilename"),"")
            . iif(verFlags & 0x400,"|" verGetStdValue(fi,sSubBlock "ProductName"),"")
            . iif(verFlags & 0x800,"|" verGetStdValue(fi,sSubBlock "ProductVersion"),"")
            . iif(verFlags & 0x1000,"|" verGetStdValue(fi,sSubBlock "PrivateBuild"),"")
            . iif(verFlags & 0x2000,"|" verGetStdValue(fi,sSubBlock "SpecialBuild"),"")
            . iif(verFlags & 0x4000,"|" verGetStdValue(fi,sSubBlock "LegalTrademarks1")
                                  . "|" verGetStdValue(fi,sSubBlock "LegalTrademarks2"),"")
      }
   }
   if (verFlags & 0x8000)
   {  dummy=
      version=|%version%|
      stringReplace,version,version,|v0.0|
      loop,parse,version,|
         if (A_LoopField)
            dummy:=dummy . delim . A_LoopField
      return strMid(dummy,2)
   }
   if (delim<>"|")
      stringReplace,version,version,|,%delim%,all
   return version
}

verGetStdValue(byref fi, value)        ;;
{  fiValue#:=0
   dummy:=0
   if !dllCall("version\VerQueryValueA",str,fi, str,value, uintp,fiValue#, uintp,dummy)
      return
   ifEqual,dummy,0, return

   len:=dllCall("lstrlenA",uint,fiValue#)
   varSetCapacity(fiValue,len+1,0)
   dllCall("RtlMoveMemory",str,fiValue, uint,fiValue#, uint,len)

      __trim:=A_AutoTrim
      AutoTrim,on
   fiValue=%fiValue%
      AutoTrim,%__trim%

   return fiValue
}
fmtHex(num,digits=8)                  ;; without "0x" padded with "0" ;;
{  varSetCapacity(s,digits+8,asc("0"))
   __format:=A_FormatInteger
   setformat,integer,hex
   num+=0
   s:=s . num
   stringReplace,s,s,0x
   setformat,integer,%__format%
   return strRight(s,digits)
}
iif(expr, a, b)                            ;;
{
   if (expr)
      return a
   else
      return b
}
strLeft(s, n)                            ;;
{
   stringLeft,s,s,%n%
   return s
}
strRight(s, n)                            ;;
{
   stringRight,s,s,%n%
   return s
}
strMid(s, begin, n=0x7FFF, Left=0) ; if L<>0 then mid to the left  ;;
{
   if Left=0
      stringMid,s,s,%begin%,%n%
   else
      stringMid,s,s,%begin%,%n%,L
   return s
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4) ;;
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
   Loop %pSize%  ; Build the integer by adding up its bytes.
      result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
   if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
      return result  ; Signed vs. unsigned doesn't matter in these cases.
   ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
   return -(0xFFFFFFFF - result + 1)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) ;;
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
   Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
      DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}

switch(idx,val1="",val2="",val3="",val4="",val5="",val6="",val7="",val8=""
          ,val9="",val10="",val11="",val12="",val13="",val14="",val15="",val16="")   ;;
{
   return val%idx%
}



Hi wOxxOm, I'm planning to try to combine your script with tinku's search with indexing script to have a way to quickly search through this info.

Do you see any problem in using this script to scan through every executable on a computer? And I was also wondering if you had updated the script, or switched to something else?

A thought: For my purposes it makes sense to have the script (or the parent script that calls it) disable last access time stamping (if enabled), and re-enable it on exit (or otherwise stop the script from updating access times). Many defraggers can use that info to place the most used files (as determined by access time stamps) in the fastest areas of the hard drive, but naturally that only works if your antivirus scans, search indexing runs, and other programs don't update them.

_________________
Hardware: 1.8 GHz laptop with 4 GB ram, Windows XP/SP3
Software: Prevx, Privatefirewall, KeyScrambler.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 13th, 2011, 8:52 am 
Offline

Joined: May 9th, 2009, 11:55 am
Posts: 15
This function no longer work with the latest Version v1.0.92.02. Can any body please update it to work with the latest AHK?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 13th, 2011, 11:14 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
You could try my FileGetVersionInfo_AW()


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 29 posts ]  Go to page Previous  1, 2

All times are UTC [ DST ]


Who is online

Users browsing this forum: oldbrother and 12 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group