2

I want to add version informations (for a specific language) to another exes that does not have such informations (at all).

I tried with BeginUpdateResource/UpdateResource/EndUpdateResource but all I succedeed is to create "Version >> 1 >> Unknown string", not "Version >> 1 >> CompanyName/VersionNumber/Description..." and their values.

I searched on Google and here but I couldn't find something useful. Only incomplete code which I didn't know how to finish.

Thank you.

Edit:

Here is the code that I use now:

procedure SetExeInfo(const ExeName, ResName, ResValue: string);
var
   ResourceHandle: THandle;
   DataLength: DWord;
   Data: array of Char;
   Ok: Boolean;
   i: Integer;

begin
   ResourceHandle := BeginUpdateResource(pChar(ExeName), False);
   if (ResourceHandle <> 0) then
   begin
      DataLength := 8;
      SetLength(Data, 8);
      for i := 0 to 7 do
         Data[i] := 'z';
      Ok := True;
      if (not UpdateResource(ResourceHandle, RT_VERSION, pChar(#49#0), LANG_SYSTEM_DEFAULT {MakeLangID(LANG_NEUTRAL, SUBLANG_NEUTRAL)}, Data, DataLength)) then
         Ok := False;

      if (not EndUpdateResource(ResourceHandle, False)) then
         Ok := False;

      if (Ok) then
         ShowMessage('Update of resources successful!')
      else
         ShowMessage('Update of resources failed!');

   end;
end;

Last edit:

I haven't specified in my question that I can't transfer the informations from another exe because I haven't seen the point to do this, since I haven't said specifically that I take the version info from another exe. Looks I was wrong, sorry.

menjaraz
  • 7,551
  • 4
  • 41
  • 81
DavidB
  • 177
  • 10
  • You could post that unfinished code, so someone can help you finish it. – GolezTrol Oct 18 '11 at 16:41
  • @GolezTrol I added one of those "unfinished codes" which I tried to modify. – DavidB Oct 18 '11 at 16:53
  • 2
    Possible duplicate of [set-exe-versioninfo](http://stackoverflow.com/questions/7796246/set-exe-versioninfo) – LU RD Oct 18 '11 at 18:07
  • @LU RD I don't think so, because in that answer it shows how to transfer the informations from one exe to another. But I want to add the informations to the output exe without taking them from the other exe. In that answer it doesn't show hot to create VERSIONINFO and fill it with these informations. GetVersionFileInfo does it only by extracting it from another exe file, which I don't have. – DavidB Oct 18 '11 at 18:48
  • @DavidB, in the link I gave there [updated-setversion-exe-to-set-file-version-info-in-res-or-ex](http://www.jasontpenny.com/blog/2009/09/05/updated-setversion-exe-to-set-file-version-info-in-res-or-exe/), is a full implementation of what you want. – LU RD Oct 18 '11 at 18:56
  • @LU RD I tried SetVersion.exe and I received this error: "Exception: No VersionInfo found in test.exe". It means that the code will work ONLY if there is a VersionInfo in the exe, which means that the code from this program can ONLY modify VersionInfo that it found in the file. I looked at the source code and I don't see how I could change it to make it add VersionInfo (not just modify it) but I'm open to suggestions... – DavidB Oct 18 '11 at 19:30
  • Why don't you link a template version resource to your exe which you can then modify and add to the target exe. Otherwise you are into [`VS_VERSIONINFO`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms647001(v=vs.85).aspx) hacking. – David Heffernan Oct 18 '11 at 19:35
  • @David Heffernan Hacking? I hate hackers, to say that I'm hacking it's like an insult to me. I'm (we're) far from this. Those exes are the property of the company where I work and we have the legal right to modify them as we please. Ok, I'll try your way: could you show me a small example on how to do this...? Just how to modify the "Comments" for example. Thank you. – DavidB Oct 18 '11 at 19:51
  • 2
    I most definitely didn't mean hacking in a derogatory way. I just meant that creating a brand new `VS_VERSIONINFO` is pretty messy because it's not a real structure. And anyway, there's nothing wrong with a bit of hacking. It's cracking that's bad. – David Heffernan Oct 18 '11 at 19:53
  • @David Heffernan I understand, no problem. Anyway, I asked you about an example because in all of these links I don't see how to modify informations <> VersionNumber (in SetVersion.exe it shows only how to modify VersionNumber). – DavidB Oct 18 '11 at 20:02
  • well I've no experience of this, sorry – David Heffernan Oct 18 '11 at 20:03
  • @DavidB, have you studied the unit unitResourceVersionInfo.pas ? – LU RD Oct 18 '11 at 20:09
  • @LU RD Yes, I have studied this unit from top to bottom but still I can't see how to set informations <> VersionNumber... – DavidB Oct 19 '11 at 07:00
  • @DavidB, the TVersionResourceDetails class exposes the property FileVersion, which is used by the SetVersion.exe example. This class also exposes the properties FileFlags,ProductVersion and mechanics for setting/changing keys/key values. This class is derived from TResourceDetails which exposes CodePage and ResourceLanguage. Am I forgetting something ? – LU RD Oct 19 '11 at 08:00

2 Answers2

4

Here is some working code to add or replace the version numbers:

type
 VERSIONHEADER = packed record
   wLength: word;
   wValueLength: word;
   wType: word;
   Key: array[0..16] of WideChar;   // 'VS_VERSION_INFO'
   Version: VS_FIXEDFILEINFO;
 end;

  (...)
  var ToolPath: TFileName;    // = exe containing a reference version resource
      ExeFullPath: TFileName; // = destination exe
      Maj, Min: cardinal; // expected UPDATED Version number
      VersionHandle, VersionRes: THandle;
      VersionSize: DWORD;
      Version: array of AnsiChar;
      Ver: ^VERSIONHEADER;
  (...)
  VersionSize := GetFileVersionInfoSize(pointer(ToolPath),VersionHandle);
  if (VersionSize<>0) and (Maj<>0) then
  begin
    SetLength(Version,VersionSize);
    Ver := pointer(Version);
    GetFileVersionInfo(pointer(ToolPath),0,VersionSize,Ver);
    if Ver^.Version.dwSignature=$feef04bd then
    begin
      Ver^.Version.dwFileVersionMS := MAKELONG(Min,Maj);
      Ver^.Version.dwProductVersionMS := Ver^.Version.dwFileVersionMS;
      VersionRes := BeginUpdateResource(Pointer(ExeFullPath),False);
      UpdateResource(VersionRes,RT_VERSION,MAKEINTRESOURCE(VS_VERSION_INFO),
        1033,Ver,VersionSize);
      EndUpdateResource(VersionRes,false);
    end;
  end;

It will add or update the numeric version numbers of an existing executable (ExeFullPath), replacing it with a supplied executable resource (ToolPath - may be paramstr(0) to copy some existing generic version information, or even ExeFullPath to update the version numbers).

Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
2

RT_VERSION resource is not just eight bytes long. It's VERSIONINFO instead, with fixed size and variable strings. See VERSIONINFO resource - MSDN for details.

CodeProject has some sample code for you: Updating version information at run-time.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • I knew that it's not 8 bytes long, I just tried to see how it writes in exe. Thank you for the links but I don't know C/C++. Could you please show me how to do this in Delphi code..? Thank you. – DavidB Oct 18 '11 at 17:47
  • http://stackoverflow.com/questions/762778/using-delphi-to-modify-the-version-information-of-another-delphi-program - is this helpful? – Roman R. Oct 18 '11 at 17:52
  • @Roman R Unfortunately no... It's one of those "unfinished/incomplete codes" that I mentioned in the question... First answer it's very "unfinished". The second answer is kind of "needle in the haystack". – DavidB Oct 18 '11 at 18:00
  • Question is: how to create a VERSIONINFO, fill it with my informations and copy it to "Data" so I can write it in resources? – DavidB Oct 18 '11 at 18:07