0

Tried out the answers from MSDN forum & the answer mentioned in thread - How do I programmatically get the version of a DLL or EXE file? - but I always get version number as "0.0.0.0"

Right Click my DLL -> Properties -> Details -> File Version has correct value. The EXE that loads my DLL does not version info - but not sure if that would matter.

My code is below (as part of the dll)->

   std::string moduleName     = "<full absolute path to DLL that this code is part of>";
   DWORD  zero                = 0;
   uint32 verInfoLen          = 0;
   BYTE   *verInfo            = NULL;
   VS_FIXEDFILEINFO *fileInfo = NULL;
   uint32 len                 = 0;

   /* Get the size of FileVersionInfo structure */
   verInfoLen = GetFileVersionInfoSize(moduleName.c_str(), &zero);
   if (verInfoLen == 0) {
      printf("GetFileVersionInfoSize() Failed!");
      return;
   }

   /* Get FileVersionInfo structure */
   verInfo = new BYTE[verInfoLen];
   if (!GetFileVersionInfo(moduleName.c_str(), zero, verInfoLen, verInfo)) {
      printf("GetFileVersionInfo Failed!");
      return;
   }

   /* Query for File version details. */
   if (!VerQueryValue(verInfo, "\\", (LPVOID *)&fileInfo, &len)) {
      printf("VerQueryValue Failed!");
      return;
   }

   /* None of the above func calls fail - but both printf below print all zeros */
   printf("Version is %d.%d.%d.%d",
                     (fileInfo->dwProductVersionMS >> 16) & 0xff,
                     (fileInfo->dwProductVersionMS >>  0) & 0xff,
                     (fileInfo->dwProductVersionLS >> 16) & 0xff,
                     (fileInfo->dwProductVersionLS >>  0) & 0xff);

   printf("Version is %d.%d.%d.%d",
                     HIWORD(fileInfo->dwProductVersionMS),
                     LOWORD(fileInfo->dwProductVersionMS),
                     HIWORD(fileInfo->dwProductVersionLS),
                     LOWORD(fileInfo->dwProductVersionLS));

Any help appreciated !

Community
  • 1
  • 1
sskanitk
  • 475
  • 4
  • 11
  • 19
  • 1
    `_T(moduleName.c_str())` ? – Jonathan Potter Jul 22 '15 at 19:50
  • Yeah - removed the _T everywhere .... still getting 0.0.0.0 – sskanitk Jul 22 '15 at 19:53
  • It's more fun to parse the PE format, using the DLL handle you get at initialization as base address for the image. If instead you want easier code, then use e.g. `std::vector` rather than `new`-ing a byte array. For example, if the value query fails the current code leaks memory. – Cheers and hth. - Alf Jul 22 '15 at 19:54
  • Check Properties/Details for that dll. Maybe it is 0.0.0.0. Try making your own DLL with the details filled in and see what you get. You can always check it first using Properties/Details. – cup Jul 22 '15 at 19:58
  • @Cheersandhth.-Alf - I should have mentioned - I am not too familiar with WinAPI programming. Can you elaborate a bit ... ? Do you mean I should pass \VarFileInfo\Translation to VerQueryValue() func and parse the results ... ? – sskanitk Jul 22 '15 at 19:58
  • @cup The Properties -> Details -> File Version has a correct value (not 0.0.0.0) .... – sskanitk Jul 22 '15 at 19:59
  • 1
    @Cheersandhth.-Alf: FYI, you do not need to parse the PE format at all. Once the DLL is loaded, you can use `(Find|Load|Lock)Resource()` and `SizeofResource()` to access the version resource directly and make a copy of it into a temp memory buffer, and then you can pass that buffer to `VerQueryValue()`. This only works when querying for `VS_FIXEDFILEINFO` though, as `GetFileVersionInfo()` performs data patch-ups that `VerQueryValue()` requires when querying other fields, so this approach would crash without those patch-ups in place. – Remy Lebeau Jul 22 '15 at 20:06
  • @RemyLebeau: I think that if you just call resource functions then at least do that in assembly language. – Cheers and hth. - Alf Jul 22 '15 at 20:07
  • @Cheersandhth.-Alf: I use this approach all the time in C++ to retrieve `VS_FIXEDFILEINFO` without using `GetFileVersionInfo()`, it works fine without resorting to writing assembly code. – Remy Lebeau Jul 22 '15 at 20:08
  • @RemyLebeau: If it works fine then you haven't used a sufficiently low level of abstraction. Just FYI. – Cheers and hth. - Alf Jul 22 '15 at 20:09
  • @Cheersandhth.-Alf: I have no clue what you are talking about. And what makes you think I'm not using any abstraction to invoke this kind of code? – Remy Lebeau Jul 22 '15 at 20:10
  • @RemyLebeau: I think you have misunderstood something. :) – Cheers and hth. - Alf Jul 22 '15 at 20:12
  • @Remy Appears to be a rather weak attempt at humour. He's winding you up for reasons unclear. – David Heffernan Jul 23 '15 at 02:33

1 Answers1

4

You are printing out the ProductVersion fields when you should be printing out the FileVersion fields instead:

printf("Version is %d.%d.%d.%d",
                 HIWORD(fileInfo->dwFileVersionMS),
                 LOWORD(fileInfo->dwFileVersionMS),
                 HIWORD(fileInfo->dwFileVersionLS),
                 LOWORD(fileInfo->dwFileVersionLS));

Also, your code is leaking the verInfo array if GetFileVersionInfo() or VerQueryValue() fail.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Aah - dwFileVersionMS & dwFileVersionLS 0- that worked! Thanks a lot @Remy-Lebeau ! And I should probably go sit in a corner for a while now :-/ – sskanitk Jul 22 '15 at 20:54
  • @sskanitk: Probably yes, because the answer you linked to already was using `dwFileVersionMS` and `dwFileVersionLS`. Well, you learned how easy it is to break a working answer, and probably won't make the same exact mistake again ;) – Ben Voigt Jul 22 '15 at 21:01