?
Solved

Create new Version Info resource at runtime

Posted on 2006-03-24
17
Medium Priority
?
371 Views
Last Modified: 2010-04-05
I need to create a version info resource, I know how to update resources, just not how the Version info type should look.

Does any one have an example or the Version info records.
0
Comment
Question by:heretoread
  • 8
  • 7
  • 2
17 Comments
 
LVL 20

Expert Comment

by:Mark Brady
ID: 16290864
Can you explain more about what you want ?  Do you want your program to read an inf file and take the version information from this file and use it somewhere in your program ?  If so then this is simple.
I assume you have an inf text file somewhere on your PC.  Just have the program load it on formcreate proc and read the version number to a string then assing the string value to a tlabel or something similar...ie:  the form title.

Elvin
0
 
LVL 2

Author Comment

by:heretoread
ID: 16291039
Show the Properties of an exe file in explorer, Click on the version tab (If the exe has one) and notice version information.

i want to create and add a version resource to an exe.
0
 
LVL 20

Expert Comment

by:Mark Brady
ID: 16291064
ok
You need to add a version resource to your project. Basically, this is a file with the ending .rc that contains

///////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 1,0,0,1
 PRODUCTVERSION 1,0,0,1
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "Comments", "Sample Application\0"
            VALUE "CompanyName", "Microsoft Corp.\0"
            VALUE "FileDescription", "MyProject MFC Application\0"
            VALUE "FileVersion", "1, 0, 0, 1\0"
            VALUE "InternalName", "MyProject\0"
            VALUE "LegalCopyright", "Copyright (C) 1999\0"
            VALUE "OriginalFilename", "MyProject.EXE\0"
            VALUE "ProductName", "MyProject Application\0"
            VALUE "ProductVersion", "1, 0, 0, 1\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END
     
(edit the above to reflect your situation)
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 2

Author Comment

by:heretoread
ID: 16293487
I'm trying todo it without the aid of a resource compiler, I'm want to add this functionality to a small setup program i made.

So a user can choose there own parameters which then gets appended to the stub.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16306749
hello heretoread , , I have done some file building, and I really beleive that to create a Compiled Res file would take some serious hard work, with file analysis, block DWord alignment,  just look at a  .RES file for a program Version in your Hex Editor. It seems like a difficult thing, , especially for 90 points. Do you have any experience at building complex files data block by data block? Maybe you may can use the brcc32.exe for this.
0
 
LVL 2

Author Comment

by:heretoread
ID: 16310034
i have tried to analyse it, I'm able to get some info,  But iv'e never done block dword alignment etc.

90 was all the points i had at time of posting, are you able to help me, i can increase them if you can.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16314828
??
Not sure I have the time to do this kind of thing ? Even if I did take the time, I doubt you could understand the code and be able to modify it to your uses since you do not have any file building experience. I have spent a few days already, looking for info on how a Resource file structure is arranged, and something about how and why the "VERSIONINFO" resource is stuctured, here is some info for you

the Resource  .RES  file uses this data Block Header -

type

  TResDataHeader = packed record
    DataSize, HeaderSize, ResType, ResID, DataVersion: Cardinal;
    MemoryFlags, LanguageId: Word;
    Version, Characteristics: Cardinal;
    end;



and  the "VERSIONINFO" resource has a definition stucture as this -


type

  PVSFixedFileInfo = ^TVSFixedFileInfo;
  {$EXTERNALSYM tagVS_FIXEDFILEINFO}
  tagVS_FIXEDFILEINFO = packed record
    dwSignature: DWORD;        { e.g. $feef04bd }
    dwStrucVersion: DWORD;     { e.g. $00000042 = "0.42" }
    dwFileVersionMS: DWORD;    { e.g. $00030075 = "3.75" }
    dwFileVersionLS: DWORD;    { e.g. $00000031 = "0.31" }
    dwProductVersionMS: DWORD; { e.g. $00030010 = "3.10" }
    dwProductVersionLS: DWORD; { e.g. $00000031 = "0.31" }
    dwFileFlagsMask: DWORD;    { = $3F for version "0.42" }
    dwFileFlags: DWORD;        { e.g. VFF_DEBUG | VFF_PRERELEASE }
    dwFileOS: DWORD;           { e.g. VOS_DOS_WINDOWS16 }
    dwFileType: DWORD;         { e.g. VFT_DRIVER }
    dwFileSubtype: DWORD;      { e.g. VFT2_DRV_KEYBOARD }
    dwFileDateMS: DWORD;       { e.g. 0 }
    dwFileDateLS: DWORD;       { e.g. 0 }
  end;
  TVSFixedFileInfo = tagVS_FIXEDFILEINFO;
  VS_FIXEDFILEINFO = tagVS_FIXEDFILEINFO;


maybe these can help you
0
 
LVL 2

Author Comment

by:heretoread
ID: 16332775
I managed to analyse the version info resource using PE Explorer and HexWorkshop.

I'm now able to create a Version Resource header and add strings.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16336412
I have been been working on this for 5 or 6 days in what time I have available, I have looked at a Hex Editor and counted and compared byte values until I am blubbering. . . I have a makeshift file builder, but There are several aspects (the rules for info strings to be single or double null terminated, with the data block DWord aligned) that still escape me, , Either the brcc32.exe is inconsistent in it's res file string analysis, or there is some factor I am to dumb to determine. . . . This is probally the most difficult and frustrating thing I have ever tried to do here at EE
0
 
LVL 2

Author Comment

by:heretoread
ID: 16341221
i know how you feel, Took me 2 days to figre it out, Every change i thought was right took me back.

The single or null terminated strings had me going nuts, I might have got this wrong but it works.

if (Length(Key) + 1) * 2 mod 4 <> 0 then
  //Double null.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16345578
no, that's not what I'm talking about.  I have no trouble with that. . .
The brcc32.exe will sometimes use -
 'OriginalFilename'#0#0

and other times use -
 'OriginalFilename'#0

and it seems to NOT depend only on the "VALUE" string length, which I have set at an even number of charaters, and an odd number of charaters, , it seems to be inconsistant, sometimes it will double null terminate BOTH strings, and sometimes it will not, , makes no sense to me
0
 
LVL 34

Accepted Solution

by:
Slick812 earned 800 total points
ID: 16346111
Here is some code for .RES file creation that is in a button click, , , that seems to work, at least most of the time. I have no more left in me to try and figure out the inconsistancies of the brcc32.exe and version res compiling, I now feel that the double null termination of both strings is not nessary, , but what do I know.
I hope this is enough for you.


type

  TResDataHeader = packed record
    DataSize, HeaderSize, ResType, ResID, DataVersion: Cardinal;
    MemoryFlags, LanguageId: Word;
    Version, Characteristics: Cardinal;
    end;

  TVersionW = packed record
    Minor, Major, Build, Release: Word;
    end;

  TFileVerInfo = packed record
    Zero1: Word;
    cID1: Cardinal;
    cID2: Cardinal;
    FileVer: TVersionW;
    ProductVer: TVersionW;
    FileFlagsMask, FileFlags, FileOS, FileType,
    FileSubtype, FileDateMS, FileDateLS: Cardinal;
    end;

  TBlockLen = packed record
    Length, StrLen, wID: Word;
    end;

  TStrWide = record
    pText: PWideChar;
    Len: Cardinal;
    end;

  TStrInfo = (siComment, siCompName, siFileDesc, siFileVer, siIntName, siLegalCopy,
              siLegalTrade, siOrFileName, siProdName, siProdVer);

  TStrBlock = (sbVerInfo, sbStrFlInfo, sbLangID, sbVarInfo, sbTrans);

  TAryUserStr = Array[TStrInfo] of WideString;

  TAryInfoStr = Array[TStrInfo] of TStrWide;

  TAryBlockStr = Array[TStrBlock] of TStrWide;



procedure TForm1.sbut_MakeResFileClick(Sender: TObject);
const
ZeroNull: Word = 0;

aryInfo: TAryInfoStr = ((pText: 'Comment'#0; Len: 18),
             (pText: 'CompanyName'#0; Len: 26),
             (pText: 'FileDescription'#0; Len: 34),
             (pText: 'FileVersion'#0; Len: 26),
             (pText: 'InternalName'; Len: 26),
             (pText: 'LegalCopyright'; Len: 30),
             (pText: 'LegalTrademarks'#0; Len: 34),
             (pText: 'OriginalFilename'; Len: 34),
             (pText: 'ProductName'#0; Len: 26),
             (pText: 'ProductVersion'; Len: 30));

aryBlock: TAryBlockStr = ((pText: 'VS_VERSION_INFO'; Len: 32),
             (pText: 'StringFileInfo'; Len: 30),
             (pText: '040904E4'; Len: 18),// US English Unicode, should be consistant in all Lang values of RES
             (pText: 'VarFileInfo'#0; Len: 26),
             (pText: 'Translation'#0; Len: 26));


var
ResFile: TFileStream;
aFilename: String;
DataHeader: TResDataHeader;
FlVerInfo: TFileVerInfo;
aCard: Cardinal;
SizeT, StrSize, LangSize: Word;
BlkLen: TBlockLen;
aryUser: TAryUserStr;
si: TStrInfo;


begin
aryUser[siComment] := 'Program to View';
aryUser[siCompName] := 'Bottom Feeder';
aryUser[siFileDesc] := 'Barely Working';
aryUser[siFileVer] := '4.5.6.7';
aryUser[siIntName] := 'DUMP.EXE';
aryUser[siLegalCopy] := 'Bottom Feeder 2006';
//aryUser[siLegalTrade] := 'the Mark';
aryUser[siOrFileName] := 'Bottom.EXE';
aryUser[siProdName] := 'Tested and Released Bottom Program March 2006';
aryUser[siProdVer] := '4.9';


aFileName := 'E:\Borland\Delphi5\Mine\LookBut\zzTest3.rest';
ResFile := TFileStream.Create(aFileName, fmCreate);
try
ZeroMemory(@DataHeader, SizeOf(DataHeader));
DataHeader.HeaderSize := SizeOf(DataHeader);
DataHeader.ResType := MaxWord;
DataHeader.ResId := MaxWord;
ResFile.WriteBuffer(DataHeader, SizeOf(DataHeader));

DataHeader.DataSize := 10;
DataHeader.ResType := $10FFFF;
DataHeader.ResId := $1FFFF;
DataHeader.MemoryFlags := $1030;
DataHeader.LanguageId := $0409;// US English, should be consistant in all Lang values of RES
ResFile.WriteBuffer(DataHeader, SizeOf(DataHeader));



BlkLen.Length := 1;
BlkLen.StrLen := $34;
BlkLen.wID := 0;
ResFile.WriteBuffer(BlkLen, SizeOf(BlkLen));
SizeT := SizeOf(BlkLen);

ResFile.WriteBuffer(aryBlock[sbVerInfo].pText^, aryBlock[sbVerInfo].Len);
Inc(SizeT, aryBlock[sbVerInfo].Len);

with FlVerInfo do
  begin
  Zero1 := 0;
  cID1 := $FEEF04BD; // US English Unicode, should be consistant in all Lang values of RES
  cID2 := $10000;

  FileVer.Minor := 5;
  FileVer.Major := 4;
  FileVer.Build := 7;
  FileVer.Release := 6;

  ProductVer.Minor := 9;
  ProductVer.Major := 4;
  ProductVer.Build := 0;
  ProductVer.Release := 0;

  FileFlagsMask := $3F;
  FileFlags := 0;
  FileOS := 4;
  FileType := 1;
  FileSubtype := 0;
  FileDateMS := 0;
  FileDateLS := 0;
  end;
ResFile.WriteBuffer(FlVerInfo, SizeOf(FlVerInfo));
Inc(SizeT, SizeOf(FlVerInfo));
StrSize := SizeT;

BlkLen.StrLen := 0;
ResFile.WriteBuffer(BlkLen, SizeOf(BlkLen));
Inc(SizeT, SizeOf(BlkLen));
ResFile.WriteBuffer(aryBlock[sbStrFlInfo].pText^, aryBlock[sbStrFlInfo].Len);
Inc(SizeT, aryBlock[sbStrFlInfo].Len);

LangSize := SizeT;

ResFile.WriteBuffer(BlkLen, SizeOf(BlkLen));
Inc(SizeT, SizeOf(BlkLen));
ResFile.WriteBuffer(aryBlock[sbLangID].pText^, aryBlock[sbLangID].Len);
Inc(SizeT, aryBlock[sbLangID].Len);

BlkLen.wID := 1;

for si := siComment to siProdVer do
  begin
  BlkLen.StrLen := Length(aryUser[si])+1;
  if (si in [siLegalCopy, siLegalTrade, siComment]) and
     (BlkLen.StrLen = 1) then Continue;

  BlkLen.Length := SizeOf(BlkLen) + aryInfo[si].Len + (BlkLen.StrLen*2);

  ResFile.WriteBuffer(BlkLen, SizeOf(BlkLen));
  Inc(SizeT, BlkLen.Length);

  ResFile.WriteBuffer(aryInfo[si].pText^, aryInfo[si].Len);
  if BlkLen.StrLen = 1 then
    ResFile.WriteBuffer(ZeroNull, SizeOf(ZeroNull))
    else
    ResFile.WriteBuffer(aryUser[si][1], BlkLen.StrLen * 2);
   
  if BlkLen.Length mod 4 <> 0 then
    begin
    ResFile.WriteBuffer(ZeroNull, SizeOf(ZeroNull));
    Inc(SizeT, 2);

    if (si = siProdVer) then
      begin
      Inc(StrSize, 2);
      Inc(LangSize, 2);
      end;
    end;
  end;

StrSize := SizeT-StrSize;
LangSize := SizeT-LangSize;

BlkLen.Length := $44;
BlkLen.StrLen := 0;
BlkLen.wID := 0;
ResFile.WriteBuffer(BlkLen, SizeOf(BlkLen));
Inc(SizeT, SizeOf(BlkLen));
ResFile.WriteBuffer(aryBlock[sbVarInfo].pText^, aryBlock[sbVarInfo].Len);
Inc(SizeT, aryBlock[sbVarInfo].Len);

BlkLen.Length := $24;
BlkLen.StrLen := 4;

ResFile.WriteBuffer(BlkLen, SizeOf(BlkLen));
Inc(SizeT, SizeOf(BlkLen));
ResFile.WriteBuffer(aryBlock[sbTrans].pText^, aryBlock[sbTrans].Len);
Inc(SizeT, aryBlock[sbTrans].Len);

aCard := $4E40409;// US English Unicode, should be consistant in all Lang values of RES
ResFile.WriteBuffer(aCard, SizeOf(aCard));
Inc(SizeT, SizeOf(aCard));

ResFile.Position := 32;
ResFile.WriteBuffer(SizeT, SizeOf(SizeT));

ResFile.Position := 64;
ResFile.WriteBuffer(SizeT, SizeOf(SizeT));

ResFile.Position := 156;
ResFile.WriteBuffer(StrSize, SizeOf(StrSize));

ResFile.Position := 192;
ResFile.WriteBuffer(LangSize, SizeOf(LangSize));

finally
FreeAndNil(ResFile);
end;
end;
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16346131
the above tested and compared against this .RC  code -



1 VERSIONINFO DISCARDABLE
 FILEVERSION 4,5,6,7
 PRODUCTVERSION 4,9,0,0
 FILEFLAGSMASK 0x3F
 FILEFLAGS 0
 FILEOS VOS__WINDOWS32
 FILETYPE VFT_APP
 FILESUBTYPE 0
BEGIN
BLOCK "StringFileInfo"
  BEGIN
  BLOCK "040904E4" // language ID for US English
    BEGIN
    VALUE "Comment", "Program to View\0" // optional
    VALUE "CompanyName", "Bottom Feeder\0"
    VALUE "FileDescription", "Barely Working\0"
    VALUE "FileVersion", "4.5.6.7\0"
    VALUE "InternalName", "DUMP.EXE\0"
    VALUE "LegalCopyright", "Bottom Feeder 2006\0" // optional
    //VALUE "LegalTrademarks", "the Mark\0" // optional
    VALUE "OriginalFilename", "Bottom.EXE\0"
    VALUE "ProductName", "Tested and Released Bottom Program March 2006\0"
    VALUE "ProductVersion", "4.9\0"
    END
  END
BLOCK "VarFileInfo"
  BEGIN
  VALUE "Translation", 0x0409, 0x04E4 // should match Language ID Block
  END
END
0
 
LVL 2

Author Comment

by:heretoread
ID: 16346553
i found the first WORD (header size), was the complete size of the resource, not just of the first few types.

I managed to get my own Version resource code working yesturday, but as you have worked hard on yours i will accept the answer.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16348253
I really wish I would not have wasted my time on this
0
 
LVL 34

Expert Comment

by:Slick812
ID: 16348260
I reallly really really wish I would NOT have wasted my time on this
0
 
LVL 2

Author Comment

by:heretoread
ID: 16349090
I hope that wasn't aimed at me, i did say on the 30th i had got my own code working and i increased the points.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Integration Management Part 2
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses
Course of the Month13 days, 18 hours left to enroll

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question