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.
Related
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
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 have an .il file which I can compile without any problems. I can strong name it and so without any issues. But I am not able to set the file version via the attribute as I would expect it. How can I set the FileVersion for an assembly when using ilasm?
If I do a round trip I get always a .res file which does contain only binary data which is not readable. What is inside this res file and can I edit it?
The code does not work
.assembly myAssembly
{
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = { string('1.2.3.4') }
The issue can be solved by using the .res file. It is not sufficient to do a round trip with ildasm and ilasm. The IL file does not reference the .res file. I had to add it to the ilasm call manually. The data in the res file seemed to contain the infos which are written into the PE header which is ok for me.
The final command line needed was
ilasm test.il /dll /res:test.res
I still do not know what exactly is inside the res file but I can exhange it with the meta data information of any other assemlby that I create manually and then decompile it to replace the metadata of the original assembly as I need.
It seems not many people are doing such stuff.
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.
When building a Delphi 2009 component package, how do you specify which directory should contain the resulting .hpp and .lib files needed for C++ Builder users?
On the Project|Options|Delphi Compiler|Linking page, the first two items are C++Builder .hpp output directory and C++Buidler .obj output directory should do what you want. The .lib and .bpi files. However, it seems that there is a bit of a bug in how these options are passed to the compiler... I'll speak with the engineer responsible about it.
From the command-line DCC32 you can use the following to control where to place these items:
-N0<path> = unit .dcu output directory
-NH<path> = unit .hpp output directory
-NO<path> = unit .obj output directory
-NB<path> = unit .bpi output directory
Note that the -NB switch AFAICR, also controls where the .lib file goes as well.
There is a known bug: http://qc.embarcadero.com/wc/qcmain.aspx?d=67513
This is /expected/ to be fixed in the forthcoming Update 3. (Don't worry about the 10.0 resolved in build number, that is a mistake that will be corrected when Update 3 is released and all the bug fixes get synchronized back to QC)
As far as I know, you can't. None of the directory options seem to control it. However, you could probably define a post-build event (Project->Options->Build events) which would copy the files to where you wanted them.