How can I hide identifier names in compiled projects? - delphi

When I compile a project containg code such as:
ttest = record
one, two: string;
three: integer;
end;
I can see in the EXE strings like "ttest", "one", "two", and "three".
This is in any verion of Delphi, even in Free Pascal.
Is there any possibility to not put this in the compiled program? Without using packers, encrypters, or the like.

Not sure that this will help, but check out create smaller delphi xe executable, it seems like removing the RTTI could solve your problem.

Try turning off every kind of debug information you can find in the Project Options dialog (menu item Project/Options), then rebuild the whole project (i.e. not just Compile, use the Project/Build menu item so that every unit in the project is recompiled). That should fix it.
The actual options you have to deselect in the project options depend on your Delphi version: for Delphi 2006/Turbo Delphi, these include all options under Debugging on the Compiler tab (maybe except "Assertions") and on the Linker tab "Include TD32 debug info" / "Include remote debug symbols". Newer Delphi versions have a "Build Configuration" feature similar to Visual Studio, selecting "Release" here and rebuilding should remove all "telltale" debugging information.

Just avoid to put your data as published, if possible, otherwise fields names are visible. Additionally, don't forget that every method created when cliking the property inspector is automatically put as published (because they are also used in the dfm files). So each 'Button1Click' etc is visible and therefore easily localizable (method code).
Just check any program compiled with Delphi in IDA free and with the special 'Delphi string IDC script (find it at the IDA palace)'.In the Names window you'll easy see every TSomething, every TSomething published properties and methods...

I solved the problem. Using "string" in records causes that the record name is visible in executable

Related

Bug: Cannot edit hints/warnings in BPL project options

I took advantage of the (time limited) upgrade offer I received via email from Embarcadero and upgraded to Delphi XE7. I like it. Good versions like this appear ever 7 years :)
But I have a problem: I don't know how to silence some warnings. For example 'W1011 Text after final END'. The 'Project Options' box is different. All those editable values are gone. Instead I have 3 entries like 'Value from: Debug configuration - All platforms.'
Where I can configure the global "Debug configuration - All platforms" thing?
Edit: Updated after the screenshot. Old answer below labeled 'General projects' since it's still useful in the general case, for EXEs, DLLs, etc.
BPL projects in XE7 only (okay in XE6-, fixed in XE8+)
Update: this bug has been marked as resolved in XE8.
I see in your screenshot you have a BPL project open (btw, you're using the XE2 Graphics32 package in XE7 - better to use the dedicated XE7 one.)
I can verify that BPLs do not show the list of warnings and hints the way other project types do. EXEs, DLLs, etc list them, as below. I think this is a bug: RSP-8980. It is a regression from XE6; XE6 shows the hints and warnings as expected but XE7 does not.
Edit the DPROJ manually
David Heffernan points out that these options are supposed to be in the project, even though the UI isn't letting you edit them. One way would be to create another project (eg a DLL), set up the options as you need, and edit the BPL's project file (.dproj) manually to include them, copying from the correctly set up other project.
This is complicated - it's XML, you need to get all the named configurations exactly right, etc - but will mimic what the UI does for you.
BPK file
You can workaround this by specifying them in the .bpk file itself. You can see a number of project options are in the GR32 .bpk file:
The BPK is analogous to the DPR file, only for BPLs. To find this file, right-click the BPL project and click 'View Source'.
If you add the line
{$WARN GARBAGE OFF}
and rebuild (not recompile, but build) the project, you will see all units which previously showed warning W1011 now do not.
How do you know what a particular warning is called, when you have to refer to them by name not number? Look them up on this handy blog post.
I have added two Quality bug reports:
Allow hints and warnings to be referring to in compiler directives by number, not just name
Packages do not allow hints/warnings to be set in the Project Options the way other project types do
General projects
A project has a number of targets (such as Windows 32bit Debug, vs OSX 32bit Release, etc) and setting can be set for each of those. In addition, these settings are inheritable, so you can set settings for all debug targets, all release targets, etc.
In general, you should set a setting at the highest level possible, and override at the most specific level.
With that as background, to change W1011 Text after final end open the Project Options and navigate to the Hints and Warnings section. In the 'Target' dropdown combo at the top, choose the highest-level target where you want to make the change (for example, in this screenshot I've chosen 'Debug configuration - all platforms' which means that Win32 Debug and Win64 Debug and any other platform debug will use this setting with the value specified here.)
Expand the 'Output warnings' tree and ignore the dark red 'Value from Foo' nodes which are referring to the inherited values - it's impossible to use here and makes more sense for other settings. These are the ones that I think are confusing you, from your question. Instead, scroll down until you see 'Text after final end' (warnings are sorted alphabetically.)
Select it, and choose the option you're interested in.
Key things to avoid confusion:
Options are inherited
Use the combo box at the top to select the level at which you are applying the setting
Override at the most specific possible
Set at the most generic possible
When setting a value, ignore the dark red "Value from Foo" inherited nodes; just scroll down or expand, and set the setting you want

List of loaded BPL plugins pretends empty, despite the package been actually loadeed

I have project group in Delphi XE2 which function is to load plugins from packages. I created these projects:
PluginInterface.bpl – package with interfaces to plugins and to MainForm
UClassManager.pas – plugins manager
UPlugin.pas – plugins interface
MultiPlug2.exe – Main Form with configurable menu
MainUnit.pas (*.dfm) – MainForm (MDI Owner)
etc... – some forms (e.g. Splash, Database Login)
TestPlugin.bpl – Test plugin
UTestPlugin.pas – Test Plugin Interface
TestForm.pas (*.dfm) – Test Form (MDI Child).
Here are some listings.
I have problem with
procedure TMainForm.RefreshPluginsList;
var
Pair: TPair<string, TMenuItem>;
I: integer;
begin
for I := 0 to ClassManager.Count - 1 do
RegisterPlugin(ClassManager[i]);
for Pair in MenuDict do
Pair.Value.Visible := Pair.Value.Count > 0;
end;
where ClassManager.Count is always zero, so RegisterPlugin is never called. What should I do to make it 1 and to register my plugin properly?
EDIT: I removed Handles.Add(LoadPackage('PluginInterface.bpl')) as suggested. This didn't help. I see 2 instances of Manager when tracing program.
Looks like you made your EXE without using BPLs - either "Use Runtime Packages" is off, or common shared PluginInterface package is not in "Required" list.
Another possible (but less probable) reason is using weak packaging -
which also mean that UClassManager unit (including extra instances of
ClassManager function and variable) would be copied into every binary.
http://docwiki.embarcadero.com/RADStudio/XE5/en/Using_the_Weak_Packaging_Directive
You can not and should not load that package dynamically - because the link to UClassManager should be made in compile-time already. Hence LoadPackage('PluginInterface.bpl') is redundant at best and breaking at worst and should be removed.
I think you did not do it, so now you have TWO instances of ClassManager - one in EXE and another in DLL. You can check for it issuing commands like
ShowMessage(IntToHex(Integer(Pointer(ClassManager()))))
in EXE and both BPLs and seeing what those instances really were.
Read manual or some Delphi textbook about using Runtime Packages. Few examples:
http://www.obsof.com/delphi_tips/DL613.html
http://pluginmgr.dennislandi.com/
Build with runtime packages on Delphi XE2
How to divide a Delphi project into BPLs properly?
How do I call Delphi functions in a bpl from an executable?
How to program a plugin in Windows/Delphi?
http://delphi.about.com/od/objectpascalide/l/aa012301a.htm
https://groups.google.com/forum/#!topic/borland.public.delphi.vcl.components.writing/E_HyoAiai28
After properly bulding your project you can check whether your EXE actually make use of unit UClassManager from the BPL rather than making its own independent clone of it.
You can look into imported functions table and DLL dependency tree of the EXE, so to see whether EXE really does call UClassManager initialization function from the proper BPL. Some programs allowing doing this:
http://wincmd.ru/plugring/fileinfo.html (and http://www.totalcmd.net/plugring/fileinfo.html)
http://ntcore.com/exsuite.php
http://ru.wikipedia.org/wiki/Dependency_Walker
One more option is to use "Project / Analyze" command from Delphi IDE menu and check "show packages" option to see which binary file contains which unit. You can find this command after installing Project Analyzer package which is part of Jedi CodeLib as http://jcl.sf.net
PS. Since you use XE2, i suggest you to avoid using TList with binary pointers and dangerous unchecked typecasts. You better base your TClassManager upon good old TClassList (already existed in Delphi 5 and maybe even earlier) or upon TList<TPlugin>
PPS. Since you're using XE2 and dynamically loading/unloading BPLs, avoid in your packages constants (or pre-initialized variables) of array [...] of string type. They are being destroyed. I have some ideas why that might happen and how it was fixed in XE3/4 but am somewhat lazy to implement a patch. I just switched to array [....] of PChar constants for that matter.

Delphi: why breakpoints from time to time are not usable (green highlighted line on IDE)?

From time to time I lose breakpoint functionality in Delphi.
I thought this to be a Delphi 2009 issue but now I have also it in Delphi XE.
In Delphi 2009 by deleting .dproj file I made the breakpoints work again.
In Delphi XE I am not able to make breakopints appear. I have update 1 with all hotfixes applied.
Does anyone have a solution?
Debug info isn't present in the file.
Make sure that you're using the Debug configuration. (Project Manager tree, expand Build Configurations, make sure Debug is bold. If it's not, right click Debug and choose Activate from the context menu.) Make sure you then do a Build of your project, not just a Compile.
If that still doesn't work, go to Project->Options from the IDE's main menu, click on Compiling under Delphi Compiler, and check the Debugging section on the right half of the window. Make sure that Debug Information and Local Symbols are both checked. If you're trying to trace into the VCL's own source, also check Use debug .dcus (you'll want to turn this off and do a full build of your project as soon as you're done, as it gets annoying when you're debugging normally). Again, you'll want to build and not compile.
If all of the above fails, another possibility is that the code unit you have open in the Code Editor isn't the same one being seen by the compiler. Make sure you don't have multiple copies of the file on your computer in a location that the compiler might find first. If you're not sure, delete the .dcu files with that unit name and then do a build of your project, and see if the newly created .dcu is in the location you'd expect.
I found a better way.
From the Project Manager tree, right click on the project and choose "Clean" from the popupmenu.
The breakpoints reappear magically and it is a very fast method.
I suspect this happens when you have done a release build, with debug disabled. Then you switch back to debug configuration and do a compile rather than a build. The files where you can't set breakpoints correspond to those with DCUs produced by a compile with debug disabled.
Simply doing a build to re-generate all DCU files will make your breakpoints work again.
Here's one more reason to misaligned code vs breakpoint markers (blue/red "pill" in the gutter).
The editor recognices three different line endings,
CRLF (Carriage Return - Line Feed pair)
CR only
LF only
Of these, CRLF is the default in the editor.
The compiler however, doesn't seem to consider CR only as a line ending, only CRLF and LF only. Thus if your source file happens to have one or more CR only, the "blue pills" will be offset from the source.
You might have got source files with CR only EOL (end of line) character from e.g. the internet. I recall MAC OS used CR only as EOL.
To verify the EOL's in your file, you can turn on the displaying of EOL's in the editor
( Tools - Options - Editor options - Source options - Show line breaks).
The symbols look weird (see images below), but are just C on top of L for CRLF, C on top of R for CR and L on top of F for LF.
The following images show the normal EOL's (CRLF) and the EOLS's after I forced CR only for one line and LF only for another line in a hex editor. As said above, it is the CR only that offsets the break point markers from the source code.
Normal CRLF EOL's:
One line with CR only and one with LF only:
Fix
To reset all EOL's to CRLF, untick Preserve line ends in Editor Options
( Tools - Options - Editor options),
make a trivial change, so that the file is marked as modified, close the file, save changes to XYZ.pas? YES, and reopen.
Now all line endings are CRLF. Rebuilt the project and all the breakpoint balls will be in the correct locations.
Turning on remote debugging symbols did it for me (nothing else worked). Project > Options > Linking and check Include remote debug symbols.
I had the same problem with XE4. This is why I found this article a couple of hours ago. None of the above solutions worked for me. The correct solution for me - up to now - was to add "remote debug symbols" option. Strange because I don't use remote debugging. Anyway it looks OK now.
It is a bug, restarting Delphi will fix your problem.
Try remote debugging to your local PC.
Why it works: (source)
When you debug Delphi projects locally, RAD Studio does not use your RSM debug file because the compiler holds the symbol tables in memory. However, when you debug Delphi projects remotely, you must generate an RSM debug file that contains those symbol tables; otherwise, RAD Studio does not stop at your breakpoints.
Of course, you must first configure your project's "Linking" option "Map file" to "Detailed" to generate the *.rsm file. See Overview of Remote Debugging for how to get started.
I had a related problem: I lost the breakpoints in a particular file, but the other files were fine. What had happened was that I had renamed that file, but unknown to me the DCU for the old file was still being used because it was being referenced in a "uses" clause somewhere.
The solution is to manually delete all the DCUs (doing a "clean" is not enough because the old file represented by the DCU is no longer in the project) and rebuild. You will get a compile error showing the bad "uses" clauses.
Another reason for not working breakpoint could be (often tested with delphi5):
Too many procedures in a unit.
The solution is to move procedures to another unit
Although this is an old question I can confirm that this is still an issue in the current version of Delphi 10.3 Rio.
The answer above regarding line endings
https://stackoverflow.com/a/53360447/6445054
Solved the issue for me I had imported some very old Delphi code which had CR line endings
in a couple of places, as soon as I started moving code around the debugging broke completely.
The option to turn line endings on has moved slightly in Rio it's now
( Tools - Options - Editor - Source - Show line breaks).
In delphi 7 there seems to be a real bug on setting breakpoints.
I had a unit where many texts are definied in a
const constname : array[0..x] of record-type = (...);
in interface section, where record-type has some AnsiString items.
In the implementation section there are some procedures.
In some particular cases, when I set a breakpoint anywhere within a procedure, delphi does not stop at it!
Remarks: all options for debugging are set properly (as for F7 causes delphi stop at the "begin" of the program, blue dots are visible in the whole unit the line stays red while executing the app) and all DCUs that have according PAS files were deleted from all of my disks and within all folders, before I did a complete build on the whole project. So no wold files should hang around anywhere.
For testing, I renamed the PAS to another name, never ever used before, and surely nowhere else on any disk, then adapted all sources and recompiled, just to be sure that delphi and I are looking at the same PAS file - but the breakpoints did not work either.
But there another, very weird thing happened: the text consts (!) changed within my executable (not within exe file, but obviously within memory)! Those texts were checked for correctness during program start, and sometimes it complained about errors! Display of the texts in a messagebox showed, that there was changed a sinlge character within that texts, that are defined as const. For test, I tried to assign something to that consts within my code, but, as expected, compiler complained, so it cannot be an ordinary assignment that causes the change of the text. Must be a wrong pointer. Weird.
So, hours of testing followed, looking for any source code that might have set up a wrong pointer that later could cause that change in a text const. I placed the messagebox into the initialization section of the first unit within the chain of unit initialization I was able to edit, but the changed char was already there! Must be changed very early during startup of my application, then!
Finally I figured out, that the char that appeared in my texts always was an $CC - which exactly is the assembler code for INT 3, the code that delphi is using for setting a breakpoint. And when moving a breakpoint within that unit a line up or down, the position of the changed character also moves some chars left or right! And the number of characters the wrong one moved just correlated with the estimated amount of assembler coded bytes the concerned lines needed. Setting two breakpoint in lines near each other, suddenly two characters changed! When removing all breakpoints from that unit, the text remained unchanged!
So there's only one conclusion: delphi itself is changing that texts when trying to set a breakpoint and fails to do so. I was unable to get rid of this bug. None of the tips about re-synching delphi's internal bookkeeping of source and object code files did help me out!
As the concerned unit mainly consisted of {$I} lines between multiple {$IFDEF}s, for including some different, but long pascal texts, I considered delphi having problems on too long inclusions or on evaluation of conditional compiler directives. So I removed the includes and put the source text immediately into the unit, and removed the {$IFDEF}s - which compiled without errors, but setting breakpoints also changed my text constants, instead of stopping execution. All the same!
I solved this for now by splitting the unit into two units, one holding just the text consts in it's interface part, and a second one to hold the procedures. And now, without changing any compiler nor linker settings, all breakpoints do work like expected and not text is changed any more!
So, if breakpoints do not work for you, while you are sure they should, possibly delphi is the culprit and fails to set the breakpoints at the correct place. In case of it is changing just some texts, maybe that never gets to your attention. Splitting the unit helped me out, maybe that helps you, too.
If the file you're trying to set breakpoints in is part of a DLL, you need to make that DLL active by double-clicking on it in Project Manager so it turns bold, and then build it. Then the blue circles will show up next to lines where you're allowed to set breakpoints.
I solved my issue by making sure Debug was set to Local:
In my case, I was setting breakpoints in a unit that whilst open in the IDE was not part of the currently active project. Such breakpoints also show as green. IOW I was not on the right page at all.
(I discovered this after trying all of the above .)
If the project group uses packages (BPLs) ensure that none of them have any compiler warnings regarding implicitly imported units. If these exist you will only be able to step through the code via the CPU debug window.
Bit late answer but I stumbled on this problem too.
If I activated the MyPackage.bpl (bold) in the project manager with the debug configuration, then compiled it, I could see the IDE registered the debug information (blue dots on left of editor).
But when I activated my MainProject.exe (the one using MyPackage.bpl), those blue dots would disappear, indicating that the debug information is no longer present. After some head scratching, I realized that I did set up a dependency (right click on MainProject.exe -> Dependencies) on the Release configuration of MyPackage.bpl and not on the Debug configuration.
Each time I compiled MyProject.exe, it would link with the Release configuration, not the debug configuration!
So check your dependency configurations!
I had MSBuild checked under Delphi Compile (we do MS Builds). That was preventing breakpoints from working. Unchecked and it works.
By using F9 to run the app, breakpoints will work as expected. I am using XE4 and I do not know if this will "fix" prior versions of Delphi.
Since this is the best resource I found on this issue when encountering this problem with a new install of Delpi XE on a new laptop, I will just add in one more possible answer for Delphi XE.
If you are using a two monitor setup and the code editor window is on the 2nd monitor, the tooltips will not show. Works fine if the editor window is on the primary monitor. Very frustrating. May be a driver issue.

Delphi 2007 and {$IFDEF...} directive, fails to see our conditional

We have the following in our codebase, in a component file:
{$IFDEF ADO}
FDatabase : TADODatabase;
{$ELSE}
FDatabase : TODBCDatabase;
{$ENDIF}
The reason is that for various legacy applications, one or the other type of database connection and set of classes is to be used.
However, while configuring a new machine, it seems that our conditionals aren't taken into account. In the project settings, it says "ADO;DEBUG", and yet it compiles the above code with the odbc type instead.
The odd thing is that it isn't consistent. Two different units built as part of the same project uses separate settings. In other words, in one place our conditional is visible, in another it is not.
The file that compiles wrong does not have any {$UNDEF or similar directives, nor does it include any files.
What am I missing here?
Solved (ugh): Right, Delphi is just being boneheaded, or whatnot.
We found these:
I get “F1026 File not found”, OR some compiler options are not passed to the compiler from the IDE.
Configuration='Debug' Platform='BNB'
Which both mention the "Platform=BNB" setting. By enabling the diagnostic output, we see that exact value. So we try to override it per the articles, no luck, still BNB. Then we go to the project settings, turns out it can be overriden there as well, so we do that too, still no luck.
Turns out the Delphi installer, or whatnot, has added a "Platform=BNB" environment variable on operating system level, removing that, restarting Delphi, and all is well.
Well, as well as can be expected. We still have to use Delphi though.
You should always make a "build all" when you change those conditions.
It could be that one unit is actually not re-compiled. Check the following:
Is the .pas file included into the project?
Is there another file (.pas or .dcu) with the same name in the search path? It's possible the IDE sees a different file than the compiler.
Is the file actually compiled? Compare the timestamps of the .pas and the .dcu file.
Do you compile for another platform? Some compiler options are not passed unless the platform is "AnyCPU".
Whenever I encounter problems like this I brute-force delete every .dcu file in my project and component folders just in case the "Build all" doesn't remove all stale .dcus. The following recompile either solves the problem or reveals if any wrong .dcu was used.

Delphi - Class TListView not found

We have a Delphi 5 application, that is built without runtime packages, dlls or external resources (i.e. a single executable). when we install it on a clients PC we get the following error messages:
Class TListView not found
or
Class TImage not found
We have installed it on dozens of PCs before without incident, but this latest install is problematic.
The target PC is a fresh install of Windows XP (Service pack 3) with no other software installed.
It does not complain about all of the classes however just one or two. for example TPanel/ TForm/ TEdit are all OK.
Can anyone think what is causing this?
EDIT
The exe on the new PC is on 30 or so other PCs that I know of, ranging from windows XP Sp1,2,3, Windows Vista and Windows embedded. both old and new PCs were installed with an old version and then updated with the newest version. The only difference is that the version jump was higher for the latest install.
This is typically an error during the streaming of a .DFM. Usually this error occurs with TLabel components because many folks remove the TLabel fields from the form or frame in order to cut down on the clutter and reduce the instance size of the form. The common and confusing mistake they make, however, is that in their over-zealousness, they remove all TLabel references. That is when bad things start to happen. Let me run down how the streaming system locates a component's class.
Remember that the class reference in the .DFM is just a string. The streaming system has to convert this string into a class reference (TComponentClass). There are two mechanisms that the streaming system uses to do this. The first one is very simple and involves a global list of class references. You can call RegisterClass or RegisterClasses to explicitly make the streaming system aware of it. The second is much more subtle and not very well known; in fact it is all part of the "magic" of Delphi :-). When the compiler builds the form, all the fields that represent the components on the form are processed and an internal table is built as part of the RTTI or metadata for the form/frame/datamodule itself. This table contains a list of references to all the individual component types represented by the component fields. So even if a component is not in the global list, it can still be found by scanning through this compiler generated table. That is what the Classes.TReader.GetFieldClass() method does.
Back to my TLabel example, this problem is easily fixed by simply ensuring that at least one of a given component type has a field. So as long as there is at least field of type TLabel, all the other TLabels will load just fine. So in your case, make sure the TListView or TImage fields haven't been deleted.
Re0sless,
I suggest you open and close every form of your application and do a fresh build after that. If memory serves me well, that was the solution when we encountered similar problems.
You might also take a look at DFM Check to open and close all your dfm's automatically and at CnPack to help you clean your uses clause.
Regards,
Lieven
I think Lieven is definitely on the right track: simple base classes not being found during runtime are a Delphi (linker) problem. This exception is not caused by the Operating System.
My experience with similar problems: the linker generates a project with the units wrongly arranged.
Example: a form unit is linked in before the base units. Forcing the project to completely recompile/relink itself should make this exception go away.
A simple [Rebuild All] will probably not suffice. You might try to recompile without optimizations.
I have tried to reproduce this error but I have not been able to. The Delphi compiler/linker is one of the best - speed of compilation/speed of compiled exes - but this bug is definitely a show stopper.
Note: I have only experienced
this error in D5. Has anybody else
experienced this error with other
Delphi versions?
I had the same problem. Class TCheckBox not found. I usually edit large set of components through .DFM of form(for example renaming large amount of component). This error comes when I rename all CheckBox on my form through it .DFM.
I just cut all the checkbox and paste them again(So .DFM file is refreshed). The error disappeared.
I've seen a similar problem due to a file copy error. To make matters more confusing, the fault was on an intermediate media device. The issue was resolved by simply recopying the file from the existing release build.
It is probably impossible to confirm now, but it is quite possible that the problem was 'solved'; not because of the removal of an unnecessay uses clause item, but because it also involved a new copy of the executable.
The solution for all errors of this type "Class XXX not found" is simple. Open DFM file of a form in text editor and manualy remove the definition of the XXX object in it.
Change the name of the Form and save the .pas with other name. Change all references to create the new unit name if this is used in other units. Build All.
With this the error disappeared.

Resources