GetFileVersionInfo()

Just starting out? Need help? Post your questions and find answers here.
RichardL
Enthusiast
Enthusiast
Posts: 532
Joined: Sat Sep 11, 2004 11:54 am
Location: UK

GetFileVersionInfo()

Post by RichardL »

Hi,
PB seems to have a problem with the API 'GetFileVersionInfo()' function call.

Code: Select all

k$="c:\temp\test.txt"+Chr(0)
j$ = Space(256)
GetFileVersionInfo_(@k$,0,256,@j$)
Debug j$
At compile time this code gives 'GetFileVersionInfo_() is not a function, an array, or a linked list.

Any suggestions most welcome.

RichardL
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

Try this :

Code: Select all

k$="c:\temp\test.txt"+Chr(0) 
j$ = Space(256) 

OpenLibrary(0,"version.dll")
CallFunction(0,"GetFileVersionInfoA",@k$,0,256,@j$)
CloseLibrary(0)

Debug j$ 
But MSDN report : Call the GetFileVersionInfoSize function before calling the GetFileVersionInfo function.
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

Here's a hack job for you.

Code: Select all

Procedure.s GetFileVersionInfo(File.s)
   ;
   iLibrary.l
   ;
   iFunctionInfo.l
   iFunctionSize.l
   iFunctionQry.l
   ;
   HoldString.s
   ;
   HoldReturn.s
   ;
   *HoldVersion.l
   ;
   HoldResult.l
   ;
   HoldBuffer.l
   ;
   HoldEmpty.l
   ;
   *HoldInfo.VS_FIXEDFILEINFO
   ;
   iLibrary = OpenLibrary(#PB_Any, "version.dll")
   ;
   If iLibrary
      ;
      iFunctionInfo = IsFunction(iLibrary, "GetFileVersionInfoA")
      iFunctionSize = IsFunction(iLibrary, "GetFileVersionInfoSizeA")
      iFunctionQry = IsFunction(iLibrary, "VerQueryValueA")
      ;
      If iFunctionInfo And iFunctionSize And iFunctionQry
         ;
         HoldBuffer = CallFunctionFast(iFunctionSize, @File, @HoldEmpty)
         ;
         HoldReturn = Space(HoldBuffer)
         ;
         HoldResult = CallFunctionFast(iFunctionInfo, File, 0, HoldBuffer, @HoldReturn)
         ;
         HoldResult = CallFunctionFast(iFunctionQry, @HoldReturn, "\", @HoldEmpty, @HoldBuffer)
         ;
         *HoldInfo = AllocateMemory(SizeOf(VS_FIXEDFILEINFO))
         ;
         CopyMemory(HoldEmpty, *HoldInfo, SizeOf(VS_FIXEDFILEINFO))
         ;
         HoldString = Str(*HoldInfo\dwFileVersionMS >> 16 & $FFFF) + "." + Str(*HoldInfo\dwFileVersionMS & $FFFF) + "." + Str(*HoldInfo\dwFileVersionLS >> 16 & $FFFF) + "." + Str(*HoldInfo\dwFileVersionLS & $FFFF)
         ;
         CloseLibrary(iLibrary)
         ;
         FreeMemory(*HoldInfo)
         ;
         HoldReturn = Space(0)
         ;
         If HoldResult
            ;
            ProcedureReturn HoldString
            ;
         Else
            ;
            ProcedureReturn ""
            ;
         EndIf
         ;
      EndIf
      ;
      CloseLibrary(iLibrary)
      ;
   EndIf
   ;
EndProcedure
RichardL
Enthusiast
Enthusiast
Posts: 532
Joined: Sat Sep 11, 2004 11:54 am
Location: UK

Post by RichardL »

Thank you both for your kind assistance.

I'm writing some routines to interface with with one of the FTDI chips so I can read and write from PB to a USB peripheral. I needed to be sure the DLL supplied by FTDI was the most recent revision.

Some progress already, I can send a packet of 128 bytes via the USB port to the peripheral. Timeout management is also working: Tomorrow maybe the read packet side works... then use the packet read/write stuff to move large amounts of data.

Never a dull day :-)

Thanks again
RichardL
RichardL
Enthusiast
Enthusiast
Posts: 532
Joined: Sat Sep 11, 2004 11:54 am
Location: UK

Post by RichardL »

I have hit a related problem...

My understanding is that when a library is opened without a complete path name the OS looks in two places; (1) the directory the program was launched from and (2) in the System32 directory. Does anyone know if there is a fixed order for this, or alternatively is there a way of finding out which directory the DLL was launched from.

The reason for needing this information is that I need to be sure that the latest version of the DLL has been loaded; there may be two versions on the machine, one in each location.

My present plan pseudocode is like this:

GetLaunchDirectory
If EXIST LaunchDirectory\dllname.dll
R1$ =GetFileVersionInfo(....)
Endif
If EXIST .... System32\dllname.dll
R2$ =GetFileVersionInfo(....)
Endif
Determine later of R1$ and R2$
Load later version of DLL

This might be something Microsoft took account of... :?

I can code the above; but it seems a bit of a heavy way to go about things.
Any suggestions are welcomed.

RichardL
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

RichardL wrote:My understanding is that when a library is opened without a complete path name the OS looks in two places; (1) the directory the program was launched from and (2) in the System32 directory. Does anyone know if there is a fixed order for this, or alternatively is there a way of finding out which directory the DLL was launched from.
Correct, program folder (as far as I know) then fallback to system folder.
However, if the dll is allready loaded (by the system or some other program)
and in memory, then windows will use that instead.
That dll could either be one in system folder or in some other programs folder.

My advice is that unless the dll is only used by your program alone,
(in which case call it something really unique filename wise to avoid any conflict with similary named dll's)
then make a small dll installer using http://nsis.sourceforge.net/ or similar,
that way you can be sure the user has the latest (your installer will install if the user has a old, or skip if the user has a more recent version).

As far as getting the dll path, I think the method is similar/same to that of exe's.

Code: Select all

;name$ contains the name of the module (either a .dll or .exe file).
;If the file name extension is omitted, the default library extension
;.dll is appended. The file name string can include a trailing point
;character (.) to indicate that the module name has no extension.
;The string does not have to specify a path. When specifying a path,
;be sure to use backslashes (\), not forward slashes (/).
;The name is compared (case independently) to the names of modules currently
;mapped into the address space of the calling process. 

Procedure.s GetModuleFilePath(name$)
 path$=Space(#MAX_PATH)
 hndl=GetModuleHandle_(name$)
 If hndl
  If GetModuleFileName_(hndl,@path$,#MAX_PATH)>0
   path$=GetPathPart(path$)
  EndIf
 EndIf
 ProcedureReturn Trim(path$)
EndProcedure

;Returns the path or "" if failed!

Debug GetModuleFilePath("kernel32.dll")
EDIT: This should let you know where/what the loaded dll was "found" by the system.
PS! should also work with executables, read PSDK/MSDN for more info on these API calls.
NOTE! Only dll's or exe's in your process memory space will be found, anything not loaded/mapped into your programs memory space will just return ""
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Actualy, just did some tests. (XP SP2) and it seems that a program can use it's own "dll" while another program uses one found in system32 or similar.

If this is true for all windows versions since Win95, you should have no worries I guess.
Altough that depends on what the dll does obviously.
If it hooks into devices and whatnot, I'm unsure how windows handles multiple same dll's. *looks at the windows experts for some insight*

Try this example, compile this as a exe.
Put it somewhere and run it but do not click Ok. keep the program stopped there.

Now in PB IDE hit that F5 and compile/run the program.
You should see two different path's for atl.dll on those programs.
(since the PureBasic compiler folder should have a copy of atl.dll)

Code: Select all

Procedure.s GetModuleFilePath(name$)
 path$=Space(#MAX_PATH)
 hndl=GetModuleHandle_(name$)
 If hndl
  If GetModuleFileName_(hndl,@path$,#MAX_PATH)>0
   path$=GetPathPart(path$)
  EndIf
 EndIf
 ProcedureReturn Trim(path$)
EndProcedure

;Returns the path or "" if failed!

OpenLibrary(0,"atl.dll")
MessageRequester("test",GetModuleFilePath("atl.dll"))
Post Reply