Background
Upto RS10.3 I used to use Andreas Hausladen DDevExtensions to set my version number in my project sources to be the same for all modules (bpl's/exe), but unfortunately Andreas has stopped updating his tool for RS10.4 and later.
So I am looking for more comfortable ways to set a version number in my app modules than applying multi-file changes to all dproj files with NotePad++.
But... On the other side I do want to keep specific information (like file description etc) specific to the module file.
What I also would like but isnt really a requirement is to have my (c) notice, and other shared info to be centralized in a single file (preferably .rc) as well.
It is not a problem to drop the version info from the dproj files (which are a pain to maintain anyway) and have a specific .rc file for each module instead.
Another advantage would be that having one central version number and (c) file is also a lot better in svn change management since I don't have to commit each and every .dproj file because of the version/build number change.
Investigation
(To be updated as we go along)
I Checked out
How to include Subversion revision number into Delphi project
Incrementing Delphi XE project version number from command line
But those solutions are not really what I am looking for; I am not looking for scripts but a source file/project file way to accomplish my task.
So here's the Q
How can I have one single .rc file containing my version number and use it in other .rc files containing specific version info
Ah I didn't expect it to be this simple...
I Created two .rc files, one with the shared info as #defines SharedVersionDefs.rc:
#define VER_MAJ 1
#define VER_MIN 2
#define VER_SUB 3
#define VER_BUILD 8
#define VER_FILEVERSION VER_MAJ,VER_MIN,VER_SUB,VER_BUILD
#define VER_FILEVERSION_STR ""VER_MAJ,VER_MIN,VER_SUB,VER_BUILD"\0"
// in my app file and product version are the same
#define VER_PRODUCTVERSION VER_MAJ,VER_MIN,VER_SUB,VER_BUILD
#define VER_PRODUCTVERSION_STR ""VER_MAJ,VER_MIN,VER_SUB,VER_BUILD"\0"
#define VER_COMPANYNAME_STR "MyCompany\0"
#define VER_LEGALCOPYRIGHT_STR "(c) 2020 "VER_COMPANYNAME_STR"\0"
And one specific file (which would re-appear for each module with different names and contents) SpecificVersion.rc:
/* Use the shared version info from a central file */
#include "SharedVersionDefs.rc"
#ifndef DEBUG
#define VER_DEBUG 0
#else
#define VER_DEBUG VS_FF_DEBUG
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", "Specific file description"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "Specific internal name"
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "ProductName", "LCCAMQM"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
Just had to create these 2 files, set version info in the delphi dproj file to OFF, and then add the specific .rc file to the module's dproj where I want it to appear, in this case a minor delphi project:
program VersionInfoTest;
{$R 'SpecificVersion.res' 'SpecificVersion.rc'}
uses
Vcl.Forms,
uMain in 'uMain.pas' {frmMain},
uVerinfo in 'uVerinfo.pas';
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.
And I verified this worked.
ATTENTION: Due to RSP-13486 you are required to add the .rc file to the .dproj file as well. Just drag-and-drop in in there using the IDE.
More info regarding the .rc files and examples can be found on MSDN
Related
I'm using Delphi 10.0 Seattle on a machine with Windows 10.
We have a system that has several executables. We use the version information via .rc file:
1 VERSIONINFO
FILEVERSION 18,2,0,1660
PRODUCTVERSION 18,2,0,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS (VS_FF_SPECIALBUILD|VS_FF_PRERELEASE)
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041604E4"
BEGIN
VALUE "CompanyName", "BLA BLA BLA\0"
VALUE "FileDescription", "BLA BLABLA - DESCRICAO\0"
VALUE "FileVersion", "18.2.0.1660\0"
VALUE "InternalName", "nomexecutavel.exe\0"
VALUE "LegalCopyright", "Copyright 2018\0"
VALUE "LegalTrademarks", "BLA BLA BLA é marca registrada\0"
VALUE "OriginalFilename", "nomeexecutavel.exe\0"
VALUE "ProductName", "nomedoproduto\0"
VALUE "ProductVersion", "18.2.0\0"
VALUE "SpecialBuild", "Para Homologação\0"
VALUE "GitRevision", "790d79ee92af023d6beac953072c45b0385df17f\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0416, 1252
END
END
This .rc file is compiled through brcc32.exe.
In the project file the .RES file information generated by brcc32 is loaded.
{$R VersionInfoFactor.res}
After I do the build and install on a Windows machine in Portuguese, I can view the version information by right-clicking on the executable, selecting Properties, then Details.
So far, this is nothing new, it shows the data that is informed in the .rc file.
Now, if I install this same executable on a Windows machine in another language, I can no longer view this information.
Would anyone know the cause?
Your resource script provides version info for ONLY Portuguese and no other language. So, of course, a non-Portuguese machine won't display anything meaningful.
You need to provide multiple StringFileInfo blocks, one for each language you want to support. And you should have a block for US English, which is the fallback when a block for a specific language is not provided.
You should organize the blocks in this order, per Hierarchical Organization of Resources for Localization:
US English
Neutral cultures
Specific cultures
On a side note, you don't need to invoke brcc32.exe manually. The Delphi compiler can do that for you, if you include the .rc filename in the {$R} directive:
{$R VersionInfoFactor.res VersionInfoFactor.rc}
Some of resources from .RC file are not available in resulting .exe with the ID's given in .RC file.
I have and RC file with resourcestrings with id's 10000, 10100 etc. At some reason, when I load resource with id 10000 (LoadStr(10000)) it loads another string ('Invalid field type.' - which is declared in midas.rc from VCL and has the same id).
I assumed that resources with the same id should lead to "[Error] WARNING. Duplicate resource(s)" during the build. But there is no linker-related warnings.
p.s. I'm using Delphi 2010.
Update:
Workaround on that issue is to change id from 10000 to something else. 10050, e.g.
Question:
Why there's no warnings on duplicate resources?
What could be done to prevent that problem in future?
myproject.inc
const
offLanguages = 10000;
offCurrencies = 10100;
myproject.RC file
LANGUAGE LANG_LATVIAN, SUBLANG_NEUTRAL
#include "myproject.inc"
STRINGTABLE
{
offLanguages+0, "LV"
}
.. etc...
Rc file is compiled to myproject.res file. And the resulting .res files has correct string "LV" with ID 10000 (I checked that with resource editor).
In delphi coude resources are loaded in unit's initialization part, using LoadStr function.
likeThat.pas:
unit likeThat;
interface
{$I *.inc}
{$R *.res}
// skipped
initialization
Assert(LoadStr( offLanguages )= 'LV'); // <== fails here
I use Delphi XE2 and I have a project called PGetBase. In this project, there is a module with a constant declaration. For example:
const
FragH = 5;
FragW = 4;
...
After compiling, the file is called PGetBase.exe. Is it possible to make the name of the build file dependent on the constants declared in the module, e.g. PGetBase_5_4.exe, by making use of a Post-Build event?
Add a project to the projectgroup which creates an executable that uses the same unit and changes the filename. Build and run that executable in the Post-Build event.
Microsoft Build knows nothing about the Pascal language and cannot parse the sources.
However you may extract "5" and "4" into some external text files.
const
FragH =
{$I Frag_h.txt}
;
FragW =
{$I Frag_W.txt}
;
Then make a simple program (or script: WSH, PowerShell, etc), that would be launched from post-build events.
You program would read those file and rename the Delphi-made PGetBase.exe to anything you wish.
PS. Of course one can parse the source unit to regain those constants, rather than offloading them into external storage. Comments hold the discussion pro et con.
PPS. NGLN came wit ha neat idea. Rather than parsing the file, you can just include that unit as part of your renamer project. Then you can add a pre-build event, that would compile(make) renamer and in post-buid the renamer would have those constants within itself. While calling make/dcc32 would probably be slower than just parsing the sources from inside the version-neutral pre-compiled renamer.exe, that NGLN's approach is elegant and self-contained in its own way.
I'm looking for a ready-to-use piece of code that would be able to read and modify Delphi .res files. The thing is that I need to create an application that will be compiling many Delphi projects at once (using the dcc32.exe file). However, it is necessary for me to change file version and language before compilation, and as far as I know, I have to modify the .res file to do that.
Have you come across any code that would give me an interface to .res files allowing me to modify the data contained in it? The thing is that I want to change only those two pieces of information keeping the rest unchanged. This is why I can't compile my own .res file based on a script.
An application executed from a command line would also be OK if it allows to be called with parameters and does what I need it to do.
Thank you very in advance!
If all you need is to add file version resource then create appver.rc file, compile it with brcc32 and in one of your app unit (for example appver.pas) add {$R appver.res} (as Marian noticed you must turn off Delphi project option to include version info).
I created command line programs that increase build numbers in .rc file, create new branch/tag in SVN with new version in branch name, compiles .rc to .res, and build application.
My .rc files with such info (Polish language) looks like:
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO LOADONCALL MOVEABLE DISCARDABLE IMPURE
FILEVERSION 7,28,7,17
PRODUCTVERSION 7,28,7,17
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE 0
{
BLOCK "StringFileInfo"
{
BLOCK "041504E2"
{
VALUE "CompanyName", "xxx\0"
VALUE "FileDescription", "yyy\0"
VALUE "ProductName", "zzz\0"
VALUE "FileVersion", "7.28.7.17\0"
VALUE "ProductVersion", "7.28.7.17\0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0415, 1250
}
}
For all things .res, look at Colin Wilson's "XN Resource Editor", for which he provides the source code: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm
And probably all you need is his resource utility library:
http://www.wilsonc.demon.co.uk/d9resourceutils.htm
I haven't used this source, but if I needed it, that's the first place I'd look. His resource editor is very useful, btw.
There is ChangeRes which seems to match your needs.
Check out sources:
http://code.google.com/p/gedemin/source/browse/trunk#trunk/Gedemin/Utility/IncVerRC
It is our utility which reads .RC file with version information and increments build number. We use it inside our build process. Here is an excerpt:
incverrc.exe ..\gedemin\gedemin.rc
"%delphi_path%\brcc32.exe" -fogedemin.res -i..\images gedemin.rc
"%delphi_path%\dcc32.exe" -b gedemin.dpr
The utility uses TIncVerRc class written by Chris Morris.
Check Resource Tuner Console on www.heaventools.com. They position that product for tasks like yours. Also there's a free rcstamp tool on CodeProject.
I remember reading an article or post somewhere years ago that suggested including a resource file in a project by referencing the .rc file instead of an already compiled .res file so that the resource is built as part of the project's build process.
I have a glyphs.rc file that I currently compile using the command brcc32 glyphs.rc. In my project file I then have the statement {$R Glyphs.res}.
I'd like to simplify this by changing it to something like
{$R Glyphs.rc}
but am unsure of the syntax. When I try using {$R Glyphs.rc} I get an error `
[DCC Error] E2161 Error: RLINK32: Unsupported 16bit resource in file "Glyphs.rc".
Is this approach possible with Delphi 2007?
Just add the rc file to your project via the "Project > Add to project" menu item. This creates the {$R 'myres.res' 'myres.rc'} line from the posting that TOndrej links to.
The linker can only handle res files, but you can direct the compiler to invoke the resource compiler and compile an rc script to produce a res file and link that, using a variation of the $R/$RESOURCE directive.
In your case (Delphi 2007) you should need only change:
{$r glyphs.res}
to
{$r glyphs.res glyphs.rc}
If this doesn't work on its own, try adding the RC to the project. In different versions of Delphi you may need single quotes around the filenames:
{$r 'glyphs.res' 'glyphs.rc'}
NOTE: You do still need to identify a res file, the difference is in being able to additionally identify the rc file to be compiled in order to produce the required res file in the first place.
Support for this appears to have been subject to some tinkering and in more recent versions adding the RC to the project does not always seem to be "detected" by the project until after you have then saved, closed and re-opened the project (e.g. I found this to be the case in XE4 but may also apply to other versions).
Also in some more recent versions, simply adding such a $R 'file.res' 'file.rc' declaration to the DPR causes the Project Manager to identify the referenced RC file as part of the project, but this does not seem to be the case in older versions. Again, part of the tinkering in this area it seems.
I would also note the XE4 is usually rock solid in terms of stability, but adding/removing RC files seemed to trigger an access violation when closing the IDE, though normal stability seemed to be restored when re-opening the IDE and project. i.e. it is adding/removing RC files that seems to cause a problem, not simply the fact of having the RC file in the project.
UPDATE: In recent versions of Delphi (Delphi 10.2 Berlin) you should include custom resources before {$R *.res} line, otherwise they will not be automatically compiled.
See an example here: "How do I make a PNG resource?".
I had the same problem and found out something new.
{$R glyphs.res glyphs.rc}
this is the code for compiling glyphs.rc to glyphs.res in the pre-build. (Works with Delphi XE4)
But this code ONLY works if it is in the *.dpr file! If you place this code, in a *.pas file as I did the first time, it will simply behave like {$R glyphs.res} and will not compile the RC file. Maybe this is a bug in Delphi.
I tried to do this in Delphi 2007 and it didn't work. I had put the line,
"{$R glyphs.res glyphs.rc}"
in my project file right above the "{$R *.res}" line that the IDE puts in there but when I added the rc file using the IDE, it put it above the "uses" line and then it worked.
I could not get rid from the mainicon in my application, so i made an trapgate.rc file put that file in the src directory, used:
MAINICON icon ".\Icon\MAINICON.ico"
5012 icon ".\Icon\5012.ico"
Then used BRCC32 to make from the RC a RES file, did the build and i had the correct icon.
you can also put more icons in there and switch thats why i added the line in makeres.bat
looks like this :
brcc32 folders.rc -fofolders.res
brcc32 main.rc -fomain.res
brcc32 xOutline.rc -foxOutline.res
brcc32 xSpin.rc -foxSpin.res
brcc32 credits.rc -focredits.res
brcc32 licence.rc -folicence.res
brcc32 trapgate.rc -fotrapgate.res <-- this is my icon file
So whatever you do even if you change the icon in the folder ..\icons of course be sure it has the correct name like mainicon.ico and 5012.ico
Hope that did help for does who can't change the icon in Delphi 7 itself.